diff options
87 files changed, 1095 insertions, 716 deletions
diff --git a/.travis.yml b/.travis.yml index bab02bb44..362b88224 100644 --- a/.travis.yml +++ b/.travis.yml @@ -46,10 +46,11 @@ after_success: - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get -qq install valgrind; fi - if [ "$TRAVIS_OS_NAME" = "linux" ]; then valgrind --leak-check=full --show-reachable=yes --suppressions=./libgit2_clar.supp _build/libgit2_clar -ionline; fi -# Only watch the development branch +# Only watch the development and master branches branches: only: - development + - master # Notify development list when needed notifications: diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..f4714993a --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,34 @@ +v0.21 + 1 +------ + +* File unlocks are atomic again via rename. Read-only files on Windows are + made read-write if necessary. + +* Share open packfiles across repositories to share descriptors and mmaps. + +* Use a map for the treebuilder, making insertion O(1) + +* LF -> CRLF filter refuses to handle mixed-EOL files + +* LF -> CRLF filter now runs when * text = auto (with Git for Windows 1.9.4) + +* The git_remote_set_transport function now sets a transport factory function, + rather than a pre-existing transport instance. + +* The git_clone_options struct no longer provides the ignore_cert_errors or + remote_name members for remote customization. + + Instead, the git_clone_options struct has two new members, remote_cb and + remote_cb_payload, which allow the caller to completely override the remote + creation process. If needed, the caller can use this callback to give their + remote a name other than the default (origin) or disable cert checking. + + The remote_callbacks member has been preserved for convenience, although it + is not used when a remote creation callback is supplied. + +* The git_clone_options struct now provides repository_cb and + repository_cb_payload to allow the user to create a repository with + custom options. + +* git_clone_into and git_clone_local_into have been removed from the + public API in favour of git_clone callbacks diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4efe28ed3..8ebb99154 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -22,17 +22,25 @@ Also, feel free to open an about any concerns you have. We like to use Issues for that so there is an easily accessible permanent record of the conversation. +## Libgit2 Versions + +The `master` branch is the main branch where development happens. +Releases are tagged +(e.g. [v0.21.0](https://github.com/libgit2/libgit2/releases/tag/v0.21.0) ) +and when a critical bug fix needs to be backported, it will be done on a +`<tag>-maint` maintenance branch. + ## Reporting Bugs First, know which version of libgit2 your problem is in and include it in your bug report. This can either be a tag (e.g. -[v0.17.0](https://github.com/libgit2/libgit2/tree/v0.17.0) ) or a commit -SHA (e.g. +[v0.17.0](https://github.com/libgit2/libgit2/releases/tag/v0.17.0) ) or a +commit SHA (e.g. [01be7863](https://github.com/libgit2/libgit2/commit/01be786319238fd6507a08316d1c265c1a89407f) -). Using [`git describe`](http://git-scm.com/docs/git-describe) is a great -way to tell us what version you're working with. +). Using [`git describe`](http://git-scm.com/docs/git-describe) is a +great way to tell us what version you're working with. -If you're not running against the latest `development` branch version, +If you're not running against the latest `master` branch version, please compile and test against that to avoid re-reporting an issue that's already been fixed. @@ -44,25 +52,33 @@ out a way to help you. ## Pull Requests -Our work flow is a typical GitHub flow, where contributors fork the -[libgit2 repository](https://github.com/libgit2/libgit2), make their changes -on branch, and submit a -[Pull Request](https://help.github.com/articles/using-pull-requests) -(a.k.a. "PR"). +Our work flow is a [typical GitHub flow](https://guides.github.com/introduction/flow/index.html), +where contributors fork the [libgit2 repository](https://github.com/libgit2/libgit2), +make their changes on branch, and submit a +[Pull Request](https://help.github.com/articles/using-pull-requests) (a.k.a. "PR"). +Pull requests should usually be targeted at the `master` branch. Life will be a lot easier for you (and us) if you follow this pattern -(i.e. fork, named branch, submit PR). If you use your fork's `development` -branch, things can get messy. +(i.e. fork, named branch, submit PR). If you use your fork's `master` +branch directly, things can get messy. + +Please include a nice description of your changes when you submit your PR; +if we have to read the whole diff to figure out why you're contributing +in the first place, you're less likely to get feedback and have your change +merged in. + +If you are starting to work on a particular area, feel free to submit a PR +that highlights your work in progress (and note in the PR title that it's +not ready to merge). These early PRs are welcome and will help in getting +visibility for your fix, allow others to comment early on the changes and +also let others know that you are currently working on something. -Please include a nice description of your changes with your PR; if we have -to read the whole diff to figure out why you're contributing in the first -place, you're less likely to get feedback and have your change merged in. +Before wrapping up a PR, you should be sure to: -If you are working on a particular area then feel free to submit a PR that -highlights your work in progress (and flag in the PR title that it's not -ready to merge). This will help in getting visibility for your fix, allow -others to comment early on the changes and also let others know that you -are currently working on something. +* Write tests to cover any functional changes (ideally tests that would + have failed before the PR and now pass) +* Update documentation for any changed public APIs +* Add to the [`CHANGELOG.md`](CHANGELOG.md) file describing any major changes ## Porting Code From Other Open-Source Projects @@ -80,10 +96,10 @@ you're porting code *from* to see what you need to do. As a general rule, MIT and BSD (3-clause) licenses are typically no problem. Apache 2.0 license typically doesn't work due to GPL incompatibility. -If you are pulling in code from core Git, another project or code you've -pulled from a forum / Stack Overflow then please flag this in your PR and -also make sure you've given proper credit to the original author in the -code snippet. +If your pull request uses code from core Git, another project, or code +from a forum / Stack Overflow, then *please* flag this in your PR and make +sure you've given proper credit to the original author in the code +snippet. ## Style Guide diff --git a/PROJECTS.md b/PROJECTS.md index d17214471..5164d95b6 100644 --- a/PROJECTS.md +++ b/PROJECTS.md @@ -10,10 +10,11 @@ ideas that no one is actively working on. ## Before You Start -Please start by reading the README.md, CONTRIBUTING.md, and CONVENTIONS.md -files before diving into one of these projects. Those will explain our -work flow and coding conventions to help ensure that your work will be -easily integrated into libgit2. +Please start by reading the [README.md](README.md), +[CONTRIBUTING.md](CONTRIBUTING.md), and [CONVENTIONS.md](CONVENTIONS.md) +files before diving into one of these projects. Those explain our work +flow and coding conventions to help ensure that your work will be easily +integrated into libgit2. Next, work through the build instructions and make sure you can clone the repository, compile it, and run the tests successfully. That will make @@ -27,7 +28,7 @@ These are good small projects to get started with libgit2. * Look at the `examples/` programs, find an existing one that mirrors a core Git command and add a missing command-line option. There are many gaps right now and this helps demonstrate how to use the library. Here - are some specific ideas: + are some specific ideas (though there are many more): * Fix the `examples/diff.c` implementation of the `-B` (a.k.a. `--break-rewrites`) command line option to actually look for the optional `[<n>][/<m>]` configuration values. There is an @@ -67,19 +68,44 @@ into one of these as a first project for libgit2 - we'd rather get to know you first by successfully shipping your work on one of the smaller projects above. +Some of these projects are broken down into subprojects and/or have +some incremental steps listed towards the larger goal. Those steps +might make good smaller projects by themselves. + * Port part of the Git test suite to run against the command line emulation in examples/ + * Pick a Git command that is emulated in our examples/ area + * Extract the Git tests that exercise that command + * Convert the tests to call our emulation + * These tests could go in examples/tests/... * Fix symlink support for files in the .git directory (i.e. don't overwrite the symlinks when writing the file contents back out) * Implement a 'git describe' like API * Add hooks API to enumerate and manage hooks (not run them at this point) + * Enumeration of available hooks + * Lookup API to see which hooks have a script and get the script + * Read/write API to load a hook script and write a hook script + * Eventually, callback API to invoke a hook callback when libgit2 + executes the action in question * Isolate logic of ignore evaluation into a standalone API * Upgrade internal libxdiff code to latest from core Git -* Add a hashtable lookup for files in the index instead of binary search - every time +* Improve index internals with hashtable lookup for files instead of + using binary search every time * Make the index write the cache out to disk (with tests to gain confidence that the caching invalidation works correctly) -* Have the tree builder use a hash table when building instead of a - list. +* Tree builder improvements: + * Use a hash table when building instead of a list + * Extend to allow building a tree hierarchy * Move the tagopt mechanism to the newer git 1.9 interpretation of --tags [#2120](https://github.com/libgit2/libgit2/issues/2120) +* Apply-patch API +* Add a patch editing API to enable "git add -p" type operations +* Textconv API to filter binary data before generating diffs (something + like the current Filter API, probably). +* Performance profiling and improvement +* Build in handling of "empty tree" and "empty blob" SHAs +* Support "git replace" ref replacements +* Include conflicts in diff results and in status + * GIT_DELTA_CONFLICT for items in conflict (with multiple files) + * Appropriate flags for status +* Support sparse checkout (i.e. "core.sparsecheckout" and ".git/info/sparse-checkout") diff --git a/include/git2/clone.h b/include/git2/clone.h index 05b7522ce..fa2e25b60 100644 --- a/include/git2/clone.h +++ b/include/git2/clone.h @@ -12,6 +12,7 @@ #include "indexer.h" #include "checkout.h" #include "remote.h" +#include "transport.h" /** @@ -52,6 +53,47 @@ typedef enum { } git_clone_local_t; /** + * The signature of a function matching git_remote_create, with an additional + * void* as a callback payload. + * + * Callers of git_clone may provide a function matching this signature to override + * the remote creation and customization process during a clone operation. + * + * @param out the resulting remote + * @param repo the repository in which to create the remote + * @param name the remote's name + * @param url the remote's url + * @param payload an opaque payload + * @return 0, GIT_EINVALIDSPEC, GIT_EEXISTS or an error code + */ +typedef int (*git_remote_create_cb)( + git_remote **out, + git_repository *repo, + const char *name, + const char *url, + void *payload); + +/** + * The signature of a function matchin git_repository_init, with an + * aditional void * as callback payload. + * + * Callers of git_clone my provide a function matching this signature + * to override the repository creation and customization process + * during a clone operation. + * + * @param out the resulting repository + * @param path path in which to create the repository + * @param bare whether the repository is bare. This is the value from the clone options + * @param payload payload specified by the options + * @return 0, or a negative value to indicate error + */ +typedef int (*git_repository_create_cb)( + git_repository **out, + const char *path, + int bare, + void *payload); + +/** * Clone options structure * * Use the GIT_CLONE_OPTIONS_INIT to get the default settings, like this: @@ -72,7 +114,11 @@ typedef struct git_clone_options { git_checkout_options checkout_opts; /** - * Callbacks to use for reporting fetch progress. + * Callbacks to use for reporting fetch progress, and for acquiring + * credentials in the event they are needed. This parameter is ignored if + * the remote_cb parameter is set; if you provide a remote creation + * callback, then you have the opportunity to configure remote callbacks in + * provided function. */ git_remote_callbacks remote_callbacks; @@ -83,23 +129,11 @@ typedef struct git_clone_options { int bare; /** - * Set to 1 if errors validating the remote host's certificate - * should be ignored. - */ - int ignore_cert_errors; - - /** * Whether to use a fetch or copy the object database. */ git_clone_local_t local; /** - * The name to be given to the remote that will be - * created. The default is "origin". - */ - const char *remote_name; - - /** * The name of the branch to checkout. NULL means use the * remote's default branch. */ @@ -110,6 +144,33 @@ typedef struct git_clone_options { * use the default signature using the config. */ git_signature *signature; + + /** + * A callback used to create the new repository into which to + * clone. If NULL, the 'bare' field will be used to determine + * whether to create a bare repository. + */ + git_repository_create_cb repository_cb; + + /** + * An opaque payload to pass to the git_repository creation callback. + * This parameter is ignored unless repository_cb is non-NULL. + */ + void *repository_cb_payload; + + /** + * A callback used to create the git_remote, prior to its being + * used to perform the clone operation. See the documentation for + * git_remote_create_cb for details. This parameter may be NULL, + * indicating that git_clone should provide default behavior. + */ + git_remote_create_cb remote_cb; + + /** + * An opaque payload to pass to the git_remote creation callback. + * This parameter is ignored unless remote_cb is non-NULL. + */ + void *remote_cb_payload; } git_clone_options; #define GIT_CLONE_OPTIONS_VERSION 1 @@ -130,9 +191,9 @@ GIT_EXTERN(int) git_clone_init_options( /** * Clone a remote repository. * - * This version handles the simple case. If you'd like to create the - * repository or remote with non-default settings, you can create and - * configure them and then use `git_clone_into()`. + * By default this creates its repository and initial remote to match + * git's defaults. You can use the options in the callback to + * customize how these are created. * * @param out pointer that will receive the resulting repository object * @param url the remote repository to clone @@ -149,59 +210,6 @@ GIT_EXTERN(int) git_clone( const char *local_path, const git_clone_options *options); -/** - * Clone into a repository - * - * After creating the repository and remote and configuring them for - * paths and callbacks respectively, you can call this function to - * perform the clone operation and optionally checkout files. - * - * @param repo the repository to use - * @param remote the remote repository to clone from - * @param co_opts options to use during checkout - * @param branch the branch to checkout after the clone, pass NULL for the - * remote's default branch - * @param signature The identity used when updating the reflog. - * @return 0 on success, any non-zero return value from a callback - * function, or a negative value to indicate an error (use - * `giterr_last` for a detailed error message) - */ -GIT_EXTERN(int) git_clone_into( - git_repository *repo, - git_remote *remote, - const git_checkout_options *co_opts, - const char *branch, - const git_signature *signature); - -/** - * Perform a local clone into a repository - * - * A "local clone" bypasses any git-aware protocols and simply copies - * over the object database from the source repository. It is often - * faster than a git-aware clone, but no verification of the data is - * performed, and can copy over too much data. - * - * @param repo the repository to use - * @param remote the remote repository to clone from - * @param co_opts options to use during checkout - * @param branch the branch to checkout after the clone, pass NULL for the - * remote's default branch - * @param link wether to use hardlinks instead of copying - * objects. This is only possible if both repositories are on the same - * filesystem. - * @param signature the identity used when updating the reflog - * @return 0 on success, any non-zero return value from a callback - * function, or a negative value to indicate an error (use - * `giterr_last` for a detailed error message) - */ -GIT_EXTERN(int) git_clone_local_into( - git_repository *repo, - git_remote *remote, - const git_checkout_options *co_opts, - const char *branch, - int link, - const git_signature *signature); - /** @} */ GIT_END_DECL #endif diff --git a/include/git2/remote.h b/include/git2/remote.h index c72c9c8cc..c8b6ac97a 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -419,20 +419,19 @@ GIT_EXTERN(int) git_remote_list(git_strarray *out, git_repository *repo); GIT_EXTERN(void) git_remote_check_cert(git_remote *remote, int check); /** - * Sets a custom transport for the remote. The caller can use this function - * to bypass the automatic discovery of a transport by URL scheme (i.e. - * http://, https://, git://) and supply their own transport to be used - * instead. After providing the transport to a remote using this function, - * the transport object belongs exclusively to that remote, and the remote will - * free it when it is freed with git_remote_free. + * Sets a custom transport factory for the remote. The caller can use this + * function to override the transport used for this remote when performing + * network operations. * * @param remote the remote to configure - * @param transport the transport object for the remote to use + * @param transport_cb the function to use to create a transport + * @param payload opaque parameter passed to transport_cb * @return 0 or an error code */ GIT_EXTERN(int) git_remote_set_transport( git_remote *remote, - git_transport *transport); + git_transport_cb transport_cb, + void *payload); /** * Argument to the completion callback which tells it which operation diff --git a/include/git2/revert.h b/include/git2/revert.h index fc1767c93..ab9dd9af9 100644 --- a/include/git2/revert.h +++ b/include/git2/revert.h @@ -59,7 +59,7 @@ GIT_EXTERN(int) git_revert_init_options( * @param merge_options the merge options (or null for defaults) * @return zero on success, -1 on failure. */ -int git_revert_commit( +GIT_EXTERN(int) git_revert_commit( git_index **out, git_repository *repo, git_commit *revert_commit, diff --git a/include/git2/transport.h b/include/git2/transport.h index af7812b5d..944072632 100644 --- a/include/git2/transport.h +++ b/include/git2/transport.h @@ -11,10 +11,6 @@ #include "net.h" #include "types.h" -#ifdef GIT_SSH -#include <libssh2.h> -#endif - /** * @file git2/transport.h * @brief Git transport interfaces and functions @@ -61,14 +57,20 @@ typedef struct { char *password; } git_cred_userpass_plaintext; -#ifdef GIT_SSH -typedef LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC((*git_cred_sign_callback)); -typedef LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC((*git_cred_ssh_interactive_callback)); -#else -typedef int (*git_cred_sign_callback)(void *, ...); -typedef int (*git_cred_ssh_interactive_callback)(void *, ...); + +/* + * If the user hasn't included libssh2.h before git2.h, we need to + * define a few types for the callback signatures. + */ +#ifndef LIBSSH2_VERSION +typedef struct _LIBSSH2_SESSION LIBSSH2_SESSION; +typedef struct _LIBSSH2_USERAUTH_KBDINT_PROMPT LIBSSH2_USERAUTH_KBDINT_PROMPT; +typedef struct _LIBSSH2_USERAUTH_KBDINT_RESPONSE LIBSSH2_USERAUTH_KBDINT_RESPONSE; #endif +typedef int (*git_cred_sign_callback)(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len, const unsigned char *data, size_t data_len, void **abstract); +typedef int (*git_cred_ssh_interactive_callback)(const char* name, int name_len, const char* instruction, int instruction_len, int num_prompts, const LIBSSH2_USERAUTH_KBDINT_PROMPT* prompts, LIBSSH2_USERAUTH_KBDINT_RESPONSE* responses, void **abstract); + /** * A ssh key from disk */ diff --git a/include/git2/tree.h b/include/git2/tree.h index 56922d40b..42b68193e 100644 --- a/include/git2/tree.h +++ b/include/git2/tree.h @@ -301,8 +301,10 @@ GIT_EXTERN(const git_tree_entry *) git_treebuilder_get( * If an entry named `filename` already exists, its attributes * will be updated with the given ones. * - * The optional pointer `out` can be used to retrieve a pointer to - * the newly created/updated entry. Pass NULL if you do not need it. + * The optional pointer `out` can be used to retrieve a pointer to the + * newly created/updated entry. Pass NULL if you do not need it. The + * pointer may not be valid past the next operation in this + * builder. Duplicate the entry if you want to keep it. * * No attempt is being made to ensure that the provided oid points * to an existing git object in the object database, nor that the diff --git a/src/buf_text.c b/src/buf_text.c index 631feb3f8..8d2b141b2 100644 --- a/src/buf_text.c +++ b/src/buf_text.c @@ -123,9 +123,13 @@ int git_buf_text_lf_to_crlf(git_buf *tgt, const git_buf *src) for (; next; scan = next + 1, next = memchr(scan, '\n', end - scan)) { size_t copylen = next - scan; - /* don't convert existing \r\n to \r\r\n */ - size_t extralen = (next > start && next[-1] == '\r') ? 1 : 2; - size_t needsize = tgt->size + copylen + extralen + 1; + size_t needsize = tgt->size + copylen + 2 + 1; + + /* if we find mixed line endings, bail */ + if (next > start && next[-1] == '\r') { + git_buf_free(tgt); + return GIT_PASSTHROUGH; + } if (tgt->asize < needsize && git_buf_grow(tgt, needsize) < 0) return -1; @@ -134,8 +138,8 @@ int git_buf_text_lf_to_crlf(git_buf *tgt, const git_buf *src) memcpy(tgt->ptr + tgt->size, scan, copylen); tgt->size += copylen; } - if (extralen == 2) - tgt->ptr[tgt->size++] = '\r'; + + tgt->ptr[tgt->size++] = '\r'; tgt->ptr[tgt->size++] = '\n'; } diff --git a/src/buf_text.h b/src/buf_text.h index 3ac9d1443..e753a0244 100644 --- a/src/buf_text.h +++ b/src/buf_text.h @@ -56,9 +56,10 @@ GIT_INLINE(int) git_buf_text_puts_escape_regex(git_buf *buf, const char *string) extern void git_buf_text_unescape(git_buf *buf); /** - * Replace all \r\n with \n. Does not modify \r without trailing \n. + * Replace all \r\n with \n. * - * @return 0 on success, -1 on memory error + * @return 0 on success, -1 on memory error, GIT_PASSTHROUGH if the + * source buffer has mixed line endings. */ extern int git_buf_text_crlf_to_lf(git_buf *tgt, const git_buf *src); diff --git a/src/checkout.c b/src/checkout.c index 20763fd35..adb3c81e0 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -46,6 +46,7 @@ enum { typedef struct { git_repository *repo; + git_iterator *target; git_diff *diff; git_checkout_options opts; bool opts_free_baseline; @@ -54,6 +55,8 @@ typedef struct { git_pool pool; git_vector removes; git_vector conflicts; + git_vector *reuc; + git_vector *names; git_buf path; size_t workdir_len; git_buf tmp; @@ -138,6 +141,7 @@ static int checkout_notify( static bool checkout_is_workdir_modified( checkout_data *data, const git_diff_file *baseitem, + const git_diff_file *newitem, const git_index_entry *wditem) { git_oid oid; @@ -169,13 +173,16 @@ static bool checkout_is_workdir_modified( /* Look at the cache to decide if the workdir is modified. If not, * we can simply compare the oid in the cache to the baseitem instead - * of hashing the file. + * of hashing the file. If so, we allow the checkout to proceed if the + * oid is identical (ie, the staged item is what we're trying to check + * out.) */ if ((ie = git_index_get_bypath(data->index, wditem->path, 0)) != NULL) { 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); + return (git_oid__cmp(&baseitem->id, &ie->id) != 0 && + git_oid_cmp(&newitem->id, &ie->id) != 0); } /* depending on where base is coming from, we may or may not know @@ -401,7 +408,7 @@ static int checkout_action_with_wd( switch (delta->status) { case GIT_DELTA_UNMODIFIED: /* case 14/15 or 33 */ - if (checkout_is_workdir_modified(data, &delta->old_file, wd)) { + if (checkout_is_workdir_modified(data, &delta->old_file, &delta->new_file, wd)) { GITERR_CHECK_ERROR( checkout_notify(data, GIT_CHECKOUT_NOTIFY_DIRTY, delta, wd) ); *action = CHECKOUT_ACTION_IF(FORCE, UPDATE_BLOB, NONE); @@ -414,13 +421,13 @@ static int checkout_action_with_wd( *action = CHECKOUT_ACTION_IF(FORCE, UPDATE_BLOB, CONFLICT); break; case GIT_DELTA_DELETED: /* case 9 or 10 (or 26 but not really) */ - if (checkout_is_workdir_modified(data, &delta->old_file, wd)) + if (checkout_is_workdir_modified(data, &delta->old_file, &delta->new_file, wd)) *action = CHECKOUT_ACTION_IF(FORCE, REMOVE, CONFLICT); else *action = CHECKOUT_ACTION_IF(SAFE, REMOVE, NONE); break; case GIT_DELTA_MODIFIED: /* case 16, 17, 18 (or 36 but not really) */ - if (checkout_is_workdir_modified(data, &delta->old_file, wd)) + if (checkout_is_workdir_modified(data, &delta->old_file, &delta->new_file, wd)) *action = CHECKOUT_ACTION_IF(FORCE, UPDATE_BLOB, CONFLICT); else *action = CHECKOUT_ACTION_IF(SAFE, UPDATE_BLOB, NONE); @@ -443,7 +450,7 @@ static int checkout_action_with_wd( } else *action = CHECKOUT_ACTION_IF(FORCE, REMOVE, CONFLICT); } - else if (checkout_is_workdir_modified(data, &delta->old_file, wd)) + else if (checkout_is_workdir_modified(data, &delta->old_file, &delta->new_file, wd)) *action = CHECKOUT_ACTION_IF(FORCE, REMOVE_AND_UPDATE, CONFLICT); else *action = CHECKOUT_ACTION_IF(SAFE, REMOVE_AND_UPDATE, NONE); @@ -788,11 +795,16 @@ done: static int checkout_conflicts_load(checkout_data *data, git_iterator *workdir, git_vector *pathspec) { git_index_conflict_iterator *iterator = NULL; + git_index *index; const git_index_entry *ancestor, *ours, *theirs; checkout_conflictdata *conflict; int error = 0; - if ((error = git_index_conflict_iterator_new(&iterator, data->index)) < 0) + /* Only write conficts from sources that have them: indexes. */ + if ((index = git_iterator_get_index(data->target)) == NULL) + return 0; + + if ((error = git_index_conflict_iterator_new(&iterator, index)) < 0) goto done; data->conflicts._cmp = checkout_conflictdata_cmp; @@ -819,6 +831,10 @@ static int checkout_conflicts_load(checkout_data *data, git_iterator *workdir, g git_vector_insert(&data->conflicts, conflict); } + /* Collect the REUC and NAME entries */ + data->reuc = &index->reuc; + data->names = &index->names; + if (error == GIT_ITEROVER) error = 0; @@ -957,16 +973,20 @@ done: static int checkout_conflicts_coalesce_renames( checkout_data *data) { + git_index *index; const git_index_name_entry *name_entry; checkout_conflictdata *ancestor_conflict, *our_conflict, *their_conflict; size_t i, names; int error = 0; + if ((index = git_iterator_get_index(data->target)) == NULL) + return 0; + /* Juggle entries based on renames */ - names = git_index_name_entrycount(data->index); + names = git_index_name_entrycount(index); for (i = 0; i < names; i++) { - name_entry = git_index_name_get_byindex(data->index, i); + name_entry = git_index_name_get_byindex(index, i); if ((error = checkout_conflicts_load_byname_entry( &ancestor_conflict, &our_conflict, &their_conflict, @@ -1010,13 +1030,17 @@ done: static int checkout_conflicts_mark_directoryfile( checkout_data *data) { + git_index *index; checkout_conflictdata *conflict; const git_index_entry *entry; size_t i, j, len; const char *path; int prefixed, error = 0; - len = git_index_entrycount(data->index); + if ((index = git_iterator_get_index(data->target)) == NULL) + return 0; + + len = git_index_entrycount(index); /* Find d/f conflicts */ git_vector_foreach(&data->conflicts, i, conflict) { @@ -1027,7 +1051,7 @@ static int checkout_conflicts_mark_directoryfile( path = conflict->ours ? conflict->ours->path : conflict->theirs->path; - if ((error = git_index_find(&j, data->index, path)) < 0) { + if ((error = git_index_find(&j, index, path)) < 0) { if (error == GIT_ENOTFOUND) giterr_set(GITERR_INDEX, "Index inconsistency, could not find entry for expected conflict '%s'", path); @@ -1036,7 +1060,7 @@ static int checkout_conflicts_mark_directoryfile( } for (; j < len; j++) { - if ((entry = git_index_get_byindex(data->index, j)) == NULL) { + if ((entry = git_index_get_byindex(index, j)) == NULL) { giterr_set(GITERR_INDEX, "Index inconsistency, truncated index while loading expected conflict '%s'", path); error = -1; @@ -1802,6 +1826,24 @@ done: return error; } +static int checkout_conflict_update_index( + checkout_data *data, + checkout_conflictdata *conflict) +{ + int error = 0; + + if (conflict->ancestor) + error = git_index_add(data->index, conflict->ancestor); + + if (!error && conflict->ours) + error = git_index_add(data->index, conflict->ours); + + if (!error && conflict->theirs) + error = git_index_add(data->index, conflict->theirs); + + return error; +} + static int checkout_create_conflicts(checkout_data *data) { checkout_conflictdata *conflict; @@ -1864,6 +1906,12 @@ static int checkout_create_conflicts(checkout_data *data) else if (!error) error = checkout_write_merge(data, conflict); + /* Update the index extensions (REUC and NAME) if we're checking + * out a different index. (Otherwise just leave them there.) + */ + if (!error && (data->strategy & GIT_CHECKOUT_DONT_UPDATE_INDEX) == 0) + error = checkout_conflict_update_index(data, conflict); + if (error) break; @@ -1876,6 +1924,37 @@ static int checkout_create_conflicts(checkout_data *data) return error; } +static int checkout_extensions_update_index(checkout_data *data) +{ + const git_index_reuc_entry *reuc_entry; + const git_index_name_entry *name_entry; + size_t i; + int error = 0; + + if ((data->strategy & GIT_CHECKOUT_UPDATE_ONLY) != 0) + return 0; + + if (data->reuc) { + git_vector_foreach(data->reuc, i, reuc_entry) { + if ((error = git_index_reuc_add(data->index, reuc_entry->path, + reuc_entry->mode[0], &reuc_entry->oid[0], + reuc_entry->mode[1], &reuc_entry->oid[1], + reuc_entry->mode[2], &reuc_entry->oid[2])) < 0) + goto done; + } + } + + if (data->names) { + git_vector_foreach(data->names, i, name_entry) { + if ((error = git_index_name_add(data->index, name_entry->ancestor, + name_entry->ours, name_entry->theirs)) < 0) + goto done; + } + } + +done: + return error; +} static void checkout_data_clear(checkout_data *data) { @@ -1919,6 +1998,7 @@ static int checkout_data_init( return error; data->repo = repo; + data->target = target; GITERR_CHECK_VERSION( proposed, GIT_CHECKOUT_OPTIONS_VERSION, "git_checkout_options"); @@ -1943,15 +2023,15 @@ static int checkout_data_init( (error = git_config_refresh(cfg)) < 0) goto cleanup; - /* if we are checking out the index, don't reload, - * otherwise get index and force reload + /* Get the repository index and reload it (unless we're checking + * out the index; then it has the changes we're trying to check + * out and those should not be overwritten.) */ - if ((data->index = git_iterator_get_index(target)) != NULL) { - GIT_REFCOUNT_INC(data->index); - } else { - /* otherwise, grab and reload the index */ - if ((error = git_repository_index(&data->index, data->repo)) < 0 || - (error = git_index_read(data->index, true)) < 0) + if ((error = git_repository_index(&data->index, data->repo)) < 0) + goto cleanup; + + if (data->index != git_iterator_get_index(target)) { + if ((error = git_index_read(data->index, true)) < 0) goto cleanup; /* cannot checkout if unresolved conflicts exist */ @@ -1963,7 +2043,7 @@ static int checkout_data_init( goto cleanup; } - /* clean conflict data when doing a tree or commit checkout */ + /* clean conflict data in the current index */ git_index_name_clear(data->index); git_index_reuc_clear(data->index); } @@ -2132,6 +2212,10 @@ int git_checkout_iterator( (error = checkout_create_conflicts(&data)) < 0) goto cleanup; + if (data.index != git_iterator_get_index(target) && + (error = checkout_extensions_update_index(&data)) < 0) + goto cleanup; + assert(data.completed_steps == data.total_steps); cleanup: @@ -2154,7 +2238,7 @@ int git_checkout_index( git_index *index, const git_checkout_options *opts) { - int error; + int error, owned = 0; git_iterator *index_i; if (!index && !repo) { @@ -2162,10 +2246,16 @@ int git_checkout_index( "Must provide either repository or index to checkout"); return -1; } - if (index && repo && git_index_owner(index) != repo) { + + if (index && repo && + git_index_owner(index) && + git_index_owner(index) != repo) { giterr_set(GITERR_CHECKOUT, "Index to checkout does not match repository"); return -1; + } else if(index && repo && !git_index_owner(index)) { + GIT_REFCOUNT_OWN(index, repo); + owned = 1; } if (!repo) @@ -2178,6 +2268,9 @@ int git_checkout_index( if (!(error = git_iterator_for_index(&index_i, index, 0, NULL, NULL))) error = git_checkout_iterator(index_i, opts); + if (owned) + GIT_REFCOUNT_OWN(index, NULL); + git_iterator_free(index_i); git_index_free(index); diff --git a/src/cherrypick.c b/src/cherrypick.c index e02348a03..cdc0eaac2 100644 --- a/src/cherrypick.c +++ b/src/cherrypick.c @@ -171,7 +171,7 @@ int git_cherry_pick( char commit_oidstr[GIT_OID_HEXSZ + 1]; const char *commit_msg, *commit_summary; git_buf their_label = GIT_BUF_INIT; - git_index *index_new = NULL, *index_repo = NULL; + git_index *index_new = NULL; int error = 0; assert(repo && commit); @@ -196,12 +196,10 @@ int git_cherry_pick( (error = git_repository_head(&our_ref, repo)) < 0 || (error = git_reference_peel((git_object **)&our_commit, our_ref, GIT_OBJ_COMMIT)) < 0 || (error = git_cherry_pick_commit(&index_new, repo, commit, our_commit, opts.mainline, &opts.merge_opts)) < 0 || - (error = git_merge__indexes(repo, index_new)) < 0 || - (error = git_repository_index(&index_repo, repo)) < 0 || - (error = git_merge__append_conflicts_to_merge_msg(repo, index_repo)) < 0 || - (error = git_checkout_index(repo, index_repo, &opts.checkout_opts)) < 0) + (error = git_merge__check_result(repo, index_new)) < 0 || + (error = git_merge__append_conflicts_to_merge_msg(repo, index_new)) < 0 || + (error = git_checkout_index(repo, index_new, &opts.checkout_opts)) < 0) goto on_error; - goto done; on_error: @@ -209,7 +207,6 @@ on_error: done: git_index_free(index_new); - git_index_free(index_repo); git_commit_free(our_commit); git_reference_free(our_ref); git_buf_free(&their_label); diff --git a/src/clone.c b/src/clone.c index 6c4fb6727..8f0284ae6 100644 --- a/src/clone.c +++ b/src/clone.c @@ -24,6 +24,8 @@ #include "repository.h" #include "odb.h" +static int clone_local_into(git_repository *repo, git_remote *remote, const git_checkout_options *co_opts, const char *branch, int link, const git_signature *signature); + static int create_branch( git_reference **branch, git_repository *repo, @@ -229,6 +231,29 @@ cleanup: return retcode; } +static int default_repository_create(git_repository **out, const char *path, int bare, void *payload) +{ + GIT_UNUSED(payload); + + return git_repository_init(out, path, bare); +} + +static int default_remote_create( + git_remote **out, + git_repository *repo, + const char *name, + const char *url, + void *payload) +{ + int error; + git_remote_callbacks *callbacks = payload; + + if ((error = git_remote_create(out, repo, name, url)) < 0) + return error; + + return git_remote_set_callbacks(*out, callbacks); +} + /* * submodules? */ @@ -241,8 +266,9 @@ static int create_and_configure_origin( { int error; git_remote *origin = NULL; - const char *name; char buf[GIT_PATH_MAX]; + git_remote_create_cb remote_create = options->remote_cb; + void *payload = options->remote_cb_payload; /* If the path exists and is a dir, the url should be the absolute path */ if (git_path_root(url) < 0 && git_path_exists(url) && git_path_isdir(url)) { @@ -252,14 +278,12 @@ static int create_and_configure_origin( url = buf; } - name = options->remote_name ? options->remote_name : "origin"; - if ((error = git_remote_create(&origin, repo, name, url)) < 0) - goto on_error; - - if (options->ignore_cert_errors) - git_remote_check_cert(origin, 0); + if (!remote_create) { + remote_create = default_remote_create; + payload = (void *)&options->remote_callbacks; + } - if ((error = git_remote_set_callbacks(origin, &options->remote_callbacks)) < 0) + if ((error = remote_create(&origin, repo, "origin", url, payload)) < 0) goto on_error; if ((error = git_remote_save(origin)) < 0) @@ -307,7 +331,7 @@ static int checkout_branch(git_repository *repo, git_remote *remote, const git_c return error; } -int git_clone_into(git_repository *repo, git_remote *_remote, const git_checkout_options *co_opts, const char *branch, const git_signature *signature) +static int clone_into(git_repository *repo, git_remote *_remote, const git_checkout_options *co_opts, const char *branch, const git_signature *signature) { int error; git_buf reflog_message = GIT_BUF_INIT; @@ -381,6 +405,7 @@ int git_clone( git_remote *origin; git_clone_options options = GIT_CLONE_OPTIONS_INIT; uint32_t rmdir_flags = GIT_RMDIR_REMOVE_FILES; + git_repository_create_cb repository_cb; assert(out && url && local_path); @@ -400,17 +425,22 @@ int git_clone( if (git_path_exists(local_path)) rmdir_flags |= GIT_RMDIR_SKIP_ROOT; - if ((error = git_repository_init(&repo, local_path, options.bare)) < 0) + if (options.repository_cb) + repository_cb = options.repository_cb; + else + repository_cb = default_repository_create; + + if ((error = repository_cb(&repo, local_path, options.bare, options.repository_cb_payload)) < 0) return error; if (!(error = create_and_configure_origin(&origin, repo, url, &options))) { if (git_clone__should_clone_local(url, options.local)) { int link = options.local != GIT_CLONE_LOCAL_NO_LINKS; - error = git_clone_local_into( + error = clone_local_into( repo, origin, &options.checkout_opts, options.checkout_branch, link, options.signature); } else { - error = git_clone_into( + error = clone_into( repo, origin, &options.checkout_opts, options.checkout_branch, options.signature); } @@ -470,7 +500,7 @@ static bool can_link(const char *src, const char *dst, int link) #endif } -int git_clone_local_into(git_repository *repo, git_remote *remote, const git_checkout_options *co_opts, const char *branch, int link, const git_signature *signature) +static int clone_local_into(git_repository *repo, git_remote *remote, const git_checkout_options *co_opts, const char *branch, int link, const git_signature *signature) { int error, flags; git_repository *src; diff --git a/src/crlf.c b/src/crlf.c index 821e04eb2..93448760d 100644 --- a/src/crlf.c +++ b/src/crlf.c @@ -286,7 +286,8 @@ static int crlf_check( if (error < 0) return error; - if (ca.auto_crlf == GIT_AUTO_CRLF_FALSE) + if (ca.crlf_action == GIT_CRLF_GUESS && + ca.auto_crlf == GIT_AUTO_CRLF_FALSE) return GIT_PASSTHROUGH; if (ca.auto_crlf == GIT_AUTO_CRLF_INPUT && diff --git a/src/filebuf.c b/src/filebuf.c index d23bcc11c..25f6e52ef 100644 --- a/src/filebuf.c +++ b/src/filebuf.c @@ -334,8 +334,6 @@ int git_filebuf_commit(git_filebuf *file) file->fd = -1; - p_unlink(file->path_original); - if (p_rename(file->path_lock, file->path_original) < 0) { giterr_set(GITERR_OS, "Failed to rename lockfile to '%s'", file->path_original); goto on_error; diff --git a/src/global.c b/src/global.c index 03a4bcedf..c72bfe890 100644 --- a/src/global.c +++ b/src/global.c @@ -291,7 +291,13 @@ static git_global_st __state; int git_threads_init(void) { - init_ssl(); + static int ssl_inited = 0; + + if (!ssl_inited) { + init_ssl(); + ssl_inited = 1; + } + git_atomic_inc(&git__n_inits); return 0; } diff --git a/src/indexer.c b/src/indexer.c index 25c3d0537..8daff3dc4 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -18,6 +18,8 @@ #include "oidmap.h" #include "zstream.h" +extern git_mutex git__mwindow_mutex; + #define UINT31_MAX (0x7FFFFFFF) struct entry { @@ -433,6 +435,8 @@ static int write_at(git_indexer *idx, const void *data, git_off_t offset, size_t git_map map; int error; + assert(data && size); + /* the offset needs to be at the beginning of the a page boundary */ page_start = (offset / page_size) * page_size; page_offset = offset - page_start; @@ -451,6 +455,9 @@ static int append_to_pack(git_indexer *idx, const void *data, size_t size) { git_off_t current_size = idx->pack->mwf.size; + 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_system_set(errno); @@ -1044,6 +1051,11 @@ void git_indexer_free(git_indexer *idx) } git_vector_free_deep(&idx->deltas); - git_packfile_free(idx->pack); + + if (!git_mutex_lock(&git__mwindow_mutex)) { + git_packfile_free(idx->pack); + git_mutex_unlock(&git__mwindow_mutex); + } + git__free(idx); } diff --git a/src/merge.c b/src/merge.c index a279d31d4..68c9f66e2 100644 --- a/src/merge.c +++ b/src/merge.c @@ -2226,64 +2226,6 @@ static int merge_normalize_checkout_opts( return error; } -static int merge_affected_paths(git_vector *paths, git_repository *repo, git_index *index_new) -{ - git_tree *head_tree = NULL; - git_iterator *iter_head = NULL, *iter_new = NULL; - git_diff *merged_list = NULL; - git_diff_options opts = GIT_DIFF_OPTIONS_INIT; - git_diff_delta *delta; - size_t i; - const git_index_entry *e; - char *path; - int error = 0; - - if ((error = git_repository_head_tree(&head_tree, repo)) < 0 || - (error = git_iterator_for_tree(&iter_head, head_tree, GIT_ITERATOR_DONT_IGNORE_CASE, NULL, NULL)) < 0 || - (error = git_iterator_for_index(&iter_new, index_new, GIT_ITERATOR_DONT_IGNORE_CASE, NULL, NULL)) < 0 || - (error = git_diff__from_iterators(&merged_list, repo, iter_head, iter_new, &opts)) < 0) - goto done; - - git_vector_foreach(&merged_list->deltas, i, delta) { - path = git__strdup(delta->new_file.path); - GITERR_CHECK_ALLOC(path); - - if ((error = git_vector_insert(paths, path)) < 0) - goto on_error; - } - - for (i = 0; i < git_index_entrycount(index_new); i++) { - e = git_index_get_byindex(index_new, i); - - if (git_index_entry_stage(e) != 0 && - (git_vector_last(paths) == NULL || - strcmp(git_vector_last(paths), e->path) != 0)) { - - path = git__strdup(e->path); - GITERR_CHECK_ALLOC(path); - - if ((error = git_vector_insert(paths, path)) < 0) - goto on_error; - } - } - - goto done; - -on_error: - git_vector_foreach(paths, i, path) - git__free(path); - - git_vector_clear(paths); - -done: - git_tree_free(head_tree); - git_iterator_free(iter_head); - git_iterator_free(iter_new); - git_diff_free(merged_list); - - return error; -} - static int merge_check_index(size_t *conflicts, git_repository *repo, git_index *index_new, git_vector *merged_paths) { git_tree *head_tree = NULL; @@ -2372,99 +2314,58 @@ done: return error; } -int git_merge__indexes(git_repository *repo, git_index *index_new) +int git_merge__check_result(git_repository *repo, git_index *index_new) { - git_index *index_repo = NULL; - int index_repo_caps = 0; + git_tree *head_tree = NULL; + git_iterator *iter_head = NULL, *iter_new = NULL; + git_diff *merged_list = NULL; + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + git_diff_delta *delta; git_vector paths = GIT_VECTOR_INIT; - size_t index_conflicts = 0, wd_conflicts = 0, conflicts, i; - char *path; + size_t i, index_conflicts = 0, wd_conflicts = 0, conflicts; const git_index_entry *e; - const git_index_name_entry *name; - const git_index_reuc_entry *reuc; int error = 0; - if ((error = git_repository_index(&index_repo, repo)) < 0) - goto done; - - /* Set the index to case sensitive to handle the merge */ - index_repo_caps = git_index_caps(index_repo); - - if ((error = git_index_set_caps(index_repo, (index_repo_caps & ~GIT_INDEXCAP_IGNORE_CASE))) < 0) - goto done; - - /* Make sure the index and workdir state do not prevent merging */ - if ((error = merge_affected_paths(&paths, repo, index_new)) < 0 || - (error = merge_check_index(&index_conflicts, repo, index_new, &paths)) < 0 || - (error = merge_check_workdir(&wd_conflicts, repo, index_new, &paths)) < 0) - goto done; - - 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; - + if ((error = git_repository_head_tree(&head_tree, repo)) < 0 || + (error = git_iterator_for_tree(&iter_head, head_tree, GIT_ITERATOR_DONT_IGNORE_CASE, NULL, NULL)) < 0 || + (error = git_iterator_for_index(&iter_new, index_new, GIT_ITERATOR_DONT_IGNORE_CASE, NULL, NULL)) < 0 || + (error = git_diff__from_iterators(&merged_list, repo, iter_head, iter_new, &opts)) < 0) goto done; - } - /* Remove removed items from the index */ - git_vector_foreach(&paths, i, path) { - if (git_index_get_bypath(index_new, path, 0) == NULL) { - if ((error = git_index_remove(index_repo, path, 0)) < 0 && - error != GIT_ENOTFOUND) - goto done; - } - } - - /* Add updated items to the index */ - git_vector_foreach(&paths, i, path) { - if ((e = git_index_get_bypath(index_new, path, 0)) != NULL) { - if ((error = git_index_add(index_repo, e)) < 0) - goto done; - } + git_vector_foreach(&merged_list->deltas, i, delta) { + if ((error = git_vector_insert(&paths, (char *)delta->new_file.path)) < 0) + goto done; } - /* Add conflicts */ - git_index_conflict_cleanup(index_repo); - for (i = 0; i < git_index_entrycount(index_new); i++) { e = git_index_get_byindex(index_new, i); if (git_index_entry_stage(e) != 0 && - (error = git_index_add(index_repo, e)) < 0) - goto done; - } + (git_vector_last(&paths) == NULL || + strcmp(git_vector_last(&paths), e->path) != 0)) { - /* Add name entries */ - git_index_name_clear(index_repo); - - for (i = 0; i < git_index_name_entrycount(index_new); i++) { - name = git_index_name_get_byindex(index_new, i); - - if ((error = git_index_name_add(index_repo, - name->ancestor, name->ours, name->theirs)) < 0) - goto done; + if ((error = git_vector_insert(&paths, (char *)e->path)) < 0) + goto done; + } } - /* Add the reuc */ - git_index_reuc_clear(index_repo); - - for (i = 0; i < git_index_reuc_entrycount(index_new); i++) { - reuc = (git_index_reuc_entry *)git_index_reuc_get_byindex(index_new, i); + /* Make sure the index and workdir state do not prevent merging */ + if ((error = merge_check_index(&index_conflicts, repo, index_new, &paths)) < 0 || + (error = merge_check_workdir(&wd_conflicts, repo, index_new, &paths)) < 0) + goto done; - if ((error = git_index_reuc_add(index_repo, reuc->path, - reuc->mode[0], &reuc->oid[0], - reuc->mode[1], &reuc->oid[1], - reuc->mode[2], &reuc->oid[2])) < 0) - goto done; + 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; } done: - if (index_repo != NULL) - git_index_set_caps(index_repo, index_repo_caps); - - git_index_free(index_repo); - git_vector_free_deep(&paths); + git_vector_free(&paths); + git_tree_free(head_tree); + git_iterator_free(iter_head); + git_iterator_free(iter_new); + git_diff_free(merged_list); return error; } @@ -2657,7 +2558,7 @@ int git_merge( git_checkout_options checkout_opts; git_merge_head *ancestor_head = NULL, *our_head = NULL; git_tree *ancestor_tree = NULL, *our_tree = NULL, **their_trees = NULL; - git_index *index_new = NULL, *index_repo = NULL; + git_index *index_new = NULL; size_t i; int error = 0; @@ -2697,10 +2598,9 @@ int git_merge( /* TODO: recursive, octopus, etc... */ if ((error = git_merge_trees(&index_new, repo, ancestor_tree, our_tree, their_trees[0], merge_opts)) < 0 || - (error = git_merge__indexes(repo, index_new)) < 0 || - (error = git_repository_index(&index_repo, repo)) < 0 || - (error = git_merge__append_conflicts_to_merge_msg(repo, index_repo)) < 0 || - (error = git_checkout_index(repo, index_repo, &checkout_opts)) < 0) + (error = git_merge__check_result(repo, index_new)) < 0 || + (error = git_merge__append_conflicts_to_merge_msg(repo, index_new)) < 0 || + (error = git_checkout_index(repo, index_new, &checkout_opts)) < 0) goto on_error; goto done; @@ -2710,7 +2610,6 @@ on_error: done: git_index_free(index_new); - git_index_free(index_repo); git_tree_free(ancestor_tree); git_tree_free(our_tree); diff --git a/src/merge.h b/src/merge.h index 00f6197bf..cc17389ab 100644 --- a/src/merge.h +++ b/src/merge.h @@ -149,7 +149,7 @@ int git_merge__setup( const git_merge_head *heads[], size_t heads_len); -int git_merge__indexes(git_repository *repo, git_index *index_new); +int git_merge__check_result(git_repository *repo, git_index *index_new); int git_merge__append_conflicts_to_merge_msg(git_repository *repo, git_index *index); diff --git a/src/mwindow.c b/src/mwindow.c index 7e5fcdfbc..1d64d26a4 100644 --- a/src/mwindow.c +++ b/src/mwindow.c @@ -11,6 +11,10 @@ #include "fileops.h" #include "map.h" #include "global.h" +#include "strmap.h" +#include "pack.h" + +GIT__USE_STRMAP; #define DEFAULT_WINDOW_SIZE \ (sizeof(void*) >= 8 \ @@ -26,20 +30,127 @@ size_t git_mwindow__mapped_limit = DEFAULT_MAPPED_LIMIT; /* Whenever you want to read or modify this, grab git__mwindow_mutex */ static git_mwindow_ctl mem_ctl; -/* - * Free all the windows in a sequence, typically because we're done - * with the file +/* Global list of mwindow files, to open packs once across repos */ +git_strmap *git__pack_cache = NULL; + +/** + * Run under mwindow lock */ -void git_mwindow_free_all(git_mwindow_file *mwf) +int git_mwindow_files_init(void) { - git_mwindow_ctl *ctl = &mem_ctl; - size_t i; + if (git__pack_cache) + return 0; + + return git_strmap_alloc(&git__pack_cache); +} + +void git_mwindow_files_free(void) +{ + git_strmap *tmp = git__pack_cache; + + git__pack_cache = NULL; + git_strmap_free(tmp); +} + +int git_mwindow_get_pack(struct git_pack_file **out, const char *path) +{ + int error; + char *packname; + git_strmap_iter pos; + struct git_pack_file *pack; + + if ((error = git_packfile__name(&packname, path)) < 0) + return error; + + if (git_mutex_lock(&git__mwindow_mutex) < 0) { + giterr_set(GITERR_OS, "failed to lock mwindow mutex"); + return -1; + } + + if (git_mwindow_files_init() < 0) { + git_mutex_unlock(&git__mwindow_mutex); + git__free(packname); + return -1; + } + + pos = git_strmap_lookup_index(git__pack_cache, packname); + git__free(packname); + + if (git_strmap_valid_index(git__pack_cache, pos)) { + pack = git_strmap_value_at(git__pack_cache, pos); + git_atomic_inc(&pack->refcount); + + git_mutex_unlock(&git__mwindow_mutex); + *out = pack; + return 0; + } + + /* If we didn't find it, we need to create it */ + if ((error = git_packfile_alloc(&pack, path)) < 0) { + git_mutex_unlock(&git__mwindow_mutex); + return error; + } + + git_atomic_inc(&pack->refcount); + + git_strmap_insert(git__pack_cache, pack->pack_name, pack, error); + git_mutex_unlock(&git__mwindow_mutex); + + if (error < 0) { + git_packfile_free(pack); + return -1; + } + + *out = pack; + return 0; +} + +void git_mwindow_put_pack(struct git_pack_file *pack) +{ + int count; + git_strmap_iter pos; + + if (git_mutex_lock(&git__mwindow_mutex) < 0) + return; + + /* put before get would be a corrupted state */ + assert(git__pack_cache); + + pos = git_strmap_lookup_index(git__pack_cache, pack->pack_name); + /* if we cannot find it, the state is corrupted */ + assert(git_strmap_valid_index(git__pack_cache, pos)); + + count = git_atomic_dec(&pack->refcount); + if (count == 0) { + git_strmap_delete_at(git__pack_cache, pos); + git_packfile_free(pack); + } + + git_mutex_unlock(&git__mwindow_mutex); + return; +} +void git_mwindow_free_all(git_mwindow_file *mwf) +{ if (git_mutex_lock(&git__mwindow_mutex)) { giterr_set(GITERR_THREAD, "unable to lock mwindow mutex"); return; } + git_mwindow_free_all_locked(mwf); + + git_mutex_unlock(&git__mwindow_mutex); +} + +/* + * Free all the windows in a sequence, typically because we're done + * with the file + */ +void git_mwindow_free_all_locked(git_mwindow_file *mwf) +{ + git_mwindow_ctl *ctl = &mem_ctl; + size_t i; + /* * Remove these windows from the global list */ @@ -67,8 +178,6 @@ void git_mwindow_free_all(git_mwindow_file *mwf) mwf->windows = w->next; git__free(w); } - - git_mutex_unlock(&git__mwindow_mutex); } /* diff --git a/src/mwindow.h b/src/mwindow.h index 0018ebbf0..63418e458 100644 --- a/src/mwindow.h +++ b/src/mwindow.h @@ -36,10 +36,18 @@ typedef struct git_mwindow_ctl { } git_mwindow_ctl; int git_mwindow_contains(git_mwindow *win, git_off_t offset); -void git_mwindow_free_all(git_mwindow_file *mwf); +void git_mwindow_free_all(git_mwindow_file *mwf); /* locks */ +void git_mwindow_free_all_locked(git_mwindow_file *mwf); /* run under lock */ unsigned char *git_mwindow_open(git_mwindow_file *mwf, git_mwindow **cursor, git_off_t offset, size_t extra, unsigned int *left); int git_mwindow_file_register(git_mwindow_file *mwf); void git_mwindow_file_deregister(git_mwindow_file *mwf); void git_mwindow_close(git_mwindow **w_cursor); +int git_mwindow_files_init(void); +void git_mwindow_files_free(void); + +struct git_pack_file; /* just declaration to avoid cyclical includes */ +int git_mwindow_get_pack(struct git_pack_file **out, const char *path); +void git_mwindow_put_pack(struct git_pack_file *pack); + #endif diff --git a/src/odb_pack.c b/src/odb_pack.c index 3750da37f..1757cf920 100644 --- a/src/odb_pack.c +++ b/src/odb_pack.c @@ -210,7 +210,7 @@ static int packfile_load__cb(void *data, git_buf *path) return 0; } - error = git_packfile_alloc(&pack, path->ptr); + error = git_mwindow_get_pack(&pack, path->ptr); /* ignore missing .pack file as git does */ if (error == GIT_ENOTFOUND) { @@ -605,7 +605,7 @@ static void pack_backend__free(git_odb_backend *_backend) for (i = 0; i < backend->packs.length; ++i) { struct git_pack_file *p = git_vector_get(&backend->packs, i); - git_packfile_free(p); + git_mwindow_put_pack(p); } git_vector_free(&backend->packs); @@ -647,7 +647,7 @@ int git_odb_backend_one_pack(git_odb_backend **backend_out, const char *idx) if (pack_backend__alloc(&backend, 1) < 0) return -1; - if (git_packfile_alloc(&packfile, idx) < 0 || + if (git_mwindow_get_pack(&packfile, idx) < 0 || git_vector_insert(&backend->packs, packfile) < 0) { pack_backend__free((git_odb_backend *)backend); @@ -664,6 +664,9 @@ int git_odb_backend_pack(git_odb_backend **backend_out, const char *objects_dir) struct pack_backend *backend = NULL; git_buf path = GIT_BUF_INIT; + if (git_mwindow_files_init() < 0) + return -1; + if (pack_backend__alloc(&backend, 8) < 0) return -1; diff --git a/src/pack.c b/src/pack.c index ace7abb58..22dbd5647 100644 --- a/src/pack.c +++ b/src/pack.c @@ -968,10 +968,10 @@ void git_packfile_free(struct git_pack_file *p) cache_free(&p->bases); - git_mwindow_free_all(&p->mwf); - - if (p->mwf.fd >= 0) + if (p->mwf.fd >= 0) { + git_mwindow_free_all_locked(&p->mwf); p_close(p->mwf.fd); + } pack_index_free(p); @@ -1063,6 +1063,23 @@ cleanup: return -1; } +int git_packfile__name(char **out, const char *path) +{ + size_t path_len; + git_buf buf = GIT_BUF_INIT; + + path_len = strlen(path); + + if (path_len < strlen(".idx")) + return git_odb__error_notfound("invalid packfile path", NULL); + + if (git_buf_printf(&buf, "%.*s.pack", (int)(path_len - strlen(".idx")), path) < 0) + return -1; + + *out = git_buf_detach(&buf); + return 0; +} + int git_packfile_alloc(struct git_pack_file **pack_out, const char *path) { struct stat st; diff --git a/src/pack.h b/src/pack.h index 610e70c18..34d37d907 100644 --- a/src/pack.h +++ b/src/pack.h @@ -90,6 +90,7 @@ struct git_pack_file { git_mwindow_file mwf; git_map index_map; git_mutex lock; /* protect updates to mwf and index_map */ + git_atomic refcount; uint32_t num_objects; uint32_t num_bad_objects; @@ -123,6 +124,8 @@ typedef struct git_packfile_stream { size_t git_packfile__object_header(unsigned char *hdr, size_t size, git_otype type); +int git_packfile__name(char **out, const char *path); + int git_packfile_unpack_header( size_t *size_p, git_otype *type_p, diff --git a/src/pool.c b/src/pool.c index 146f118b4..a516ff9eb 100644 --- a/src/pool.c +++ b/src/pool.c @@ -146,7 +146,7 @@ GIT_INLINE(void) pool_remove_page( void *git_pool_malloc(git_pool *pool, uint32_t items) { git_pool_page *scan = pool->open, *prev; - uint32_t size = items * pool->item_size; + uint32_t size = ((items * pool->item_size) + 7) & ~7; void *ptr = NULL; pool->has_string_alloc = 0; diff --git a/src/refs.h b/src/refs.h index f75a4bf7e..a46b219b6 100644 --- a/src/refs.h +++ b/src/refs.h @@ -63,7 +63,7 @@ struct git_reference { } target; git_oid peel; - char name[0]; + char name[GIT_FLEX_ARRAY]; }; git_reference *git_reference__set_name(git_reference *ref, const char *name); diff --git a/src/remote.c b/src/remote.c index 47b61b1b1..e9dafa0ea 100644 --- a/src/remote.c +++ b/src/remote.c @@ -267,9 +267,11 @@ int git_remote_dup(git_remote **dest, git_remote *source) if (source->pushurl != NULL) { remote->pushurl = git__strdup(source->pushurl); - GITERR_CHECK_ALLOC(remote->pushurl); + GITERR_CHECK_ALLOC(remote->pushurl); } + remote->transport_cb = source->transport_cb; + remote->transport_cb_payload = source->transport_cb_payload; remote->repo = source->repo; remote->download_tags = source->download_tags; remote->check_cert = source->check_cert; @@ -659,8 +661,14 @@ int git_remote_connect(git_remote *remote, git_direction direction) return -1; } - /* A transport could have been supplied in advance with - * git_remote_set_transport */ + /* If we don't have a transport object yet, and the caller specified a + * custom transport factory, use that */ + if (!t && remote->transport_cb && + (error = remote->transport_cb(&t, remote, remote->transport_cb_payload)) < 0) + return error; + + /* If we still don't have a transport, then use the global + * transport registrations which map URI schemes to transport factories */ if (!t && (error = git_transport_new(&t, remote, url)) < 0) return error; @@ -1262,18 +1270,20 @@ const git_remote_callbacks *git_remote_get_callbacks(git_remote *remote) return &remote->callbacks; } -int git_remote_set_transport(git_remote *remote, git_transport *transport) +int git_remote_set_transport( + git_remote *remote, + git_transport_cb transport_cb, + void *payload) { - assert(remote && transport); - - GITERR_CHECK_VERSION(transport, GIT_TRANSPORT_VERSION, "git_transport"); + assert(remote); if (remote->transport) { giterr_set(GITERR_NET, "A transport is already bound to this remote"); return -1; } - remote->transport = transport; + remote->transport_cb = transport_cb; + remote->transport_cb_payload = payload; return 0; } diff --git a/src/remote.h b/src/remote.h index 4164a14b3..47c4f7221 100644 --- a/src/remote.h +++ b/src/remote.h @@ -22,6 +22,8 @@ struct git_remote { git_vector refs; git_vector refspecs; git_vector active_refspecs; + git_transport_cb transport_cb; + void *transport_cb_payload; git_transport *transport; git_repository *repo; git_remote_callbacks callbacks; diff --git a/src/revert.c b/src/revert.c index 9c587724b..36560a77c 100644 --- a/src/revert.c +++ b/src/revert.c @@ -174,7 +174,7 @@ int git_revert( char commit_oidstr[GIT_OID_HEXSZ + 1]; const char *commit_msg; git_buf their_label = GIT_BUF_INIT; - git_index *index_new = NULL, *index_repo = NULL; + git_index *index_new = NULL; int error; assert(repo && commit); @@ -199,10 +199,9 @@ int git_revert( (error = git_repository_head(&our_ref, repo)) < 0 || (error = git_reference_peel((git_object **)&our_commit, our_ref, GIT_OBJ_COMMIT)) < 0 || (error = git_revert_commit(&index_new, repo, commit, our_commit, opts.mainline, &opts.merge_opts)) < 0 || - (error = git_merge__indexes(repo, index_new)) < 0 || - (error = git_repository_index(&index_repo, repo)) < 0 || - (error = git_merge__append_conflicts_to_merge_msg(repo, index_repo)) < 0 || - (error = git_checkout_index(repo, index_repo, &opts.checkout_opts)) < 0) + (error = git_merge__check_result(repo, index_new)) < 0 || + (error = git_merge__append_conflicts_to_merge_msg(repo, index_new)) < 0 || + (error = git_checkout_index(repo, index_new, &opts.checkout_opts)) < 0) goto on_error; goto done; @@ -212,7 +211,6 @@ on_error: done: git_index_free(index_new); - git_index_free(index_repo); git_commit_free(our_commit); git_reference_free(our_ref); git_buf_free(&their_label); diff --git a/src/transport.c b/src/transport.c index 2194b1864..fbcda5a53 100644 --- a/src/transport.c +++ b/src/transport.c @@ -133,10 +133,11 @@ int git_transport_new(git_transport **out, git_remote *owner, const char *url) return -1; } - error = fn(&transport, owner, param); - if (error < 0) + if ((error = fn(&transport, owner, param)) < 0) return error; + GITERR_CHECK_VERSION(transport, GIT_TRANSPORT_VERSION, "git_transport"); + *out = transport; return 0; diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c index a52aacc60..82891165f 100644 --- a/src/transports/smart_protocol.c +++ b/src/transports/smart_protocol.c @@ -592,7 +592,9 @@ int git_smart__download_pack( } } else if (pkt->type == GIT_PKT_DATA) { git_pkt_data *p = (git_pkt_data *) pkt; - error = writepack->append(writepack, p->data, p->len, stats); + + if (p->len) + error = writepack->append(writepack, p->data, p->len, stats); } else if (pkt->type == GIT_PKT_FLUSH) { /* A flush indicates the end of the packfile */ git__free(pkt); diff --git a/src/transports/ssh.c b/src/transports/ssh.c index b403727c9..79a632bd5 100644 --- a/src/transports/ssh.c +++ b/src/transports/ssh.c @@ -132,11 +132,22 @@ static int ssh_stream_write( size_t len) { ssh_stream *s = (ssh_stream *)stream; + size_t off = 0; + ssize_t ret = 0; if (!s->sent_command && send_command(s) < 0) return -1; - if (libssh2_channel_write(s->channel, buffer, len) < LIBSSH2_ERROR_NONE) { + do { + ret = libssh2_channel_write(s->channel, buffer + off, len - off); + if (ret < 0) + break; + + off += ret; + + } while (off < len); + + if (ret < 0) { ssh_error(s->session, "SSH could not write data"); return -1; } diff --git a/src/tree.c b/src/tree.c index b64efe460..28190d6da 100644 --- a/src/tree.c +++ b/src/tree.c @@ -17,6 +17,8 @@ #define DEFAULT_TREE_SIZE 16 #define MAX_FILEMODE_BYTES 6 +GIT__USE_STRMAP; + static bool valid_filemode(const int filemode) { return (filemode == GIT_FILEMODE_TREE @@ -365,7 +367,8 @@ size_t git_tree_entrycount(const git_tree *tree) unsigned int git_treebuilder_entrycount(git_treebuilder *bld) { assert(bld); - return (unsigned int)bld->entrycount; + + return git_strmap_num_entries(bld->map); } static int tree_error(const char *str, const char *path) @@ -450,6 +453,7 @@ static int append_entry( git_filemode_t filemode) { git_tree_entry *entry; + int error = 0; if (!valid_entry_name(filename)) return tree_error("Failed to insert entry. Invalid name for a tree entry", filename); @@ -460,12 +464,13 @@ static int append_entry( git_oid_cpy(&entry->oid, id); entry->attr = (uint16_t)filemode; - if (git_vector_insert_sorted(&bld->entries, entry, NULL) < 0) { - git__free(entry); + git_strmap_insert(bld->map, entry->filename, entry, error); + if (error < 0) { + git_tree_entry_free(entry); + giterr_set(GITERR_TREE, "failed to append entry %s to the tree builder", filename); return -1; } - bld->entrycount++; return 0; } @@ -610,18 +615,17 @@ int git_tree__write_index( int git_treebuilder_create(git_treebuilder **builder_p, const git_tree *source) { git_treebuilder *bld; - size_t i, source_entries = DEFAULT_TREE_SIZE; + size_t i; assert(builder_p); bld = git__calloc(1, sizeof(git_treebuilder)); GITERR_CHECK_ALLOC(bld); - if (source != NULL) - source_entries = source->entries.length; - - if (git_vector_init(&bld->entries, source_entries, entry_sort_cmp) < 0) - goto on_error; + if (git_strmap_alloc(&bld->map) < 0) { + git__free(bld); + return -1; + } if (source != NULL) { git_tree_entry *entry_src; @@ -651,7 +655,8 @@ int git_treebuilder_insert( git_filemode_t filemode) { git_tree_entry *entry; - size_t pos; + int error; + git_strmap_iter pos; assert(bld && id && filename); @@ -661,22 +666,20 @@ int git_treebuilder_insert( if (!valid_entry_name(filename)) return tree_error("Failed to insert entry. Invalid name for a tree entry", filename); - if (!tree_key_search(&pos, &bld->entries, filename, strlen(filename))) { - entry = git_vector_get(&bld->entries, pos); - if (entry->removed) { - entry->removed = 0; - bld->entrycount++; - } + pos = git_strmap_lookup_index(bld->map, filename); + if (git_strmap_valid_index(bld->map, pos)) { + entry = git_strmap_value_at(bld->map, pos); } else { entry = alloc_entry(filename); GITERR_CHECK_ALLOC(entry); - if (git_vector_insert_sorted(&bld->entries, entry, NULL) < 0) { - git__free(entry); + git_strmap_insert(bld->map, entry->filename, entry, error); + + if (error < 0) { + git_tree_entry_free(entry); + giterr_set(GITERR_TREE, "failed to insert %s", filename); return -1; } - - bld->entrycount++; } git_oid_cpy(&entry->oid, id); @@ -690,17 +693,14 @@ int git_treebuilder_insert( static git_tree_entry *treebuilder_get(git_treebuilder *bld, const char *filename) { - size_t idx; - git_tree_entry *entry; + git_tree_entry *entry = NULL; + git_strmap_iter pos; assert(bld && filename); - if (tree_key_search(&idx, &bld->entries, filename, strlen(filename)) < 0) - return NULL; - - entry = git_vector_get(&bld->entries, idx); - if (entry->removed) - return NULL; + pos = git_strmap_lookup_index(bld->map, filename); + if (git_strmap_valid_index(bld->map, pos)) + entry = git_strmap_value_at(bld->map, pos); return entry; } @@ -712,35 +712,44 @@ const git_tree_entry *git_treebuilder_get(git_treebuilder *bld, const char *file int git_treebuilder_remove(git_treebuilder *bld, const char *filename) { - git_tree_entry *remove_ptr = treebuilder_get(bld, filename); + git_tree_entry *entry = treebuilder_get(bld, filename); - if (remove_ptr == NULL || remove_ptr->removed) + if (entry == NULL) return tree_error("Failed to remove entry. File isn't in the tree", filename); - remove_ptr->removed = 1; - bld->entrycount--; + git_strmap_delete(bld->map, filename); + git_tree_entry_free(entry); + return 0; } int git_treebuilder_write(git_oid *oid, git_repository *repo, git_treebuilder *bld) { int error = 0; - size_t i; + size_t i, entrycount; git_buf tree = GIT_BUF_INIT; git_odb *odb; + git_tree_entry *entry; + git_vector entries; assert(bld); - git_vector_sort(&bld->entries); + entrycount = git_strmap_num_entries(bld->map); + if (git_vector_init(&entries, entrycount, entry_sort_cmp) < 0) + return -1; - /* Grow the buffer beforehand to an estimated size */ - error = git_buf_grow(&tree, bld->entries.length * 72); + git_strmap_foreach_value(bld->map, entry, { + if (git_vector_insert(&entries, entry) < 0) + return -1; + }); - for (i = 0; i < bld->entries.length && !error; ++i) { - git_tree_entry *entry = git_vector_get(&bld->entries, i); + git_vector_sort(&entries); + + /* Grow the buffer beforehand to an estimated size */ + error = git_buf_grow(&tree, entrycount * 72); - if (entry->removed) - continue; + for (i = 0; i < entries.length && !error; ++i) { + git_tree_entry *entry = git_vector_get(&entries, i); git_buf_printf(&tree, "%o ", entry->attr); git_buf_put(&tree, entry->filename, entry->filename_len + 1); @@ -750,6 +759,8 @@ int git_treebuilder_write(git_oid *oid, git_repository *repo, git_treebuilder *b error = -1; } + git_vector_free(&entries); + if (!error && !(error = git_repository_odb__weakptr(&odb, repo))) error = git_odb_write(oid, odb, tree.ptr, tree.size, GIT_OBJ_TREE); @@ -763,31 +774,27 @@ void git_treebuilder_filter( git_treebuilder_filter_cb filter, void *payload) { - size_t i; + const char *filename; git_tree_entry *entry; assert(bld && filter); - git_vector_foreach(&bld->entries, i, entry) { - if (!entry->removed && filter(entry, payload)) { - entry->removed = 1; - bld->entrycount--; - } - } + git_strmap_foreach(bld->map, filename, entry, { + if (filter(entry, payload)) { + git_strmap_delete(bld->map, filename); + git_tree_entry_free(entry); + } + }); } void git_treebuilder_clear(git_treebuilder *bld) { - size_t i; git_tree_entry *e; assert(bld); - git_vector_foreach(&bld->entries, i, e) - git_tree_entry_free(e); - - git_vector_clear(&bld->entries); - bld->entrycount = 0; + git_strmap_foreach_value(bld->map, e, git_tree_entry_free(e)); + git_strmap_clear(bld->map); } void git_treebuilder_free(git_treebuilder *bld) @@ -796,7 +803,7 @@ void git_treebuilder_free(git_treebuilder *bld) return; git_treebuilder_clear(bld); - git_vector_free(&bld->entries); + git_strmap_free(bld->map); git__free(bld); } diff --git a/src/tree.h b/src/tree.h index f07039a07..5d27eb7c9 100644 --- a/src/tree.h +++ b/src/tree.h @@ -11,9 +11,9 @@ #include "repository.h" #include "odb.h" #include "vector.h" +#include "strmap.h" struct git_tree_entry { - uint16_t removed; uint16_t attr; git_oid oid; size_t filename_len; @@ -26,8 +26,7 @@ struct git_tree { }; struct git_treebuilder { - git_vector entries; - size_t entrycount; /* vector may contain "removed" entries */ + git_strmap *map; }; GIT_INLINE(bool) git_tree_entry__is_tree(const struct git_tree_entry *e) diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c index 34938431a..fbadb1c9e 100644 --- a/src/win32/posix_w32.c +++ b/src/win32/posix_w32.c @@ -591,6 +591,31 @@ int p_access(const char* path, mode_t mode) return _waccess(buf, mode); } +static int ensure_writable(wchar_t *fpath) +{ + DWORD attrs; + + attrs = GetFileAttributesW(fpath); + if (attrs == INVALID_FILE_ATTRIBUTES) { + if (GetLastError() == ERROR_FILE_NOT_FOUND) + return 0; + + giterr_set(GITERR_OS, "failed to get attributes"); + return -1; + } + + if (!(attrs & FILE_ATTRIBUTE_READONLY)) + return 0; + + attrs &= ~FILE_ATTRIBUTE_READONLY; + if (!SetFileAttributesW(fpath, attrs)) { + giterr_set(GITERR_OS, "failed to set attributes"); + return -1; + } + + return 0; +} + int p_rename(const char *from, const char *to) { git_win32_path wfrom; @@ -602,12 +627,13 @@ int p_rename(const char *from, const char *to) if (utf8_to_16_with_errno(wfrom, from) < 0 || utf8_to_16_with_errno(wto, to) < 0) return -1; - + /* wait up to 50ms if file is locked by another thread or process */ rename_tries = 0; rename_succeeded = 0; while (rename_tries < 10) { - if (MoveFileExW(wfrom, wto, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) != 0) { + if (ensure_writable(wto) == 0 && + MoveFileExW(wfrom, wto, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) != 0) { rename_succeeded = 1; break; } diff --git a/tests/blame/blame_helpers.c b/tests/blame/blame_helpers.c index 56240dbde..9bb77a52d 100644 --- a/tests/blame/blame_helpers.c +++ b/tests/blame/blame_helpers.c @@ -48,7 +48,7 @@ void check_blame_hunk_index(git_repository *repo, git_blame *blame, int idx, actual, expected); } cl_assert_equal_s(actual, expected); - cl_assert_equal_i(git_oid_cmp(&hunk->final_commit_id, &hunk->orig_commit_id), 0); + cl_assert_equal_oid(&hunk->final_commit_id, &hunk->orig_commit_id); if (strcmp(hunk->orig_path, orig_path)) { diff --git a/tests/checkout/binaryunicode.c b/tests/checkout/binaryunicode.c index 1172816c7..27e70d3f1 100644 --- a/tests/checkout/binaryunicode.c +++ b/tests/checkout/binaryunicode.c @@ -37,12 +37,12 @@ static void execute_test(void) /* Verify that the lenna.jpg file was checked out correctly */ cl_git_pass(git_oid_fromstr(&check, "8ab005d890fe53f65eda14b23672f60d9f4ec5a1")); cl_git_pass(git_odb_hashfile(&oid, "binaryunicode/lenna.jpg", GIT_OBJ_BLOB)); - cl_assert(git_oid_equal(&oid, &check)); + cl_assert_equal_oid(&oid, &check); /* Verify that the text file was checked out correctly */ cl_git_pass(git_oid_fromstr(&check, "965b223880dd4249e2c66a0cc0b4cffe1dc40f5a")); cl_git_pass(git_odb_hashfile(&oid, "binaryunicode/utf16_withbom_noeol_crlf.txt", GIT_OBJ_BLOB)); - cl_assert(git_oid_equal(&oid, &check)); + cl_assert_equal_oid(&oid, &check); } void test_checkout_binaryunicode__noautocrlf(void) diff --git a/tests/checkout/conflict.c b/tests/checkout/conflict.c index 2cb7c224d..b8ae80576 100644 --- a/tests/checkout/conflict.c +++ b/tests/checkout/conflict.c @@ -156,7 +156,7 @@ static void ensure_workdir_oid(const char *path, const char *oid_str) cl_git_pass(git_oid_fromstr(&expected, oid_str)); cl_git_pass(git_repository_hashfile(&actual, g_repo, path, GIT_OBJ_BLOB, NULL)); - cl_assert(git_oid_cmp(&expected, &actual) == 0); + cl_assert_equal_oid(&expected, &actual); } static void ensure_workdir_mode(const char *path, int mode) @@ -169,7 +169,7 @@ static void ensure_workdir_mode(const char *path, int mode) git_buf_joinpath(&fullpath, git_repository_workdir(g_repo), path)); cl_git_pass(p_stat(git_buf_cstr(&fullpath), &st)); - cl_assert_equal_i(mode, st.st_mode); + cl_assert_equal_i((mode & S_IRWXU), (st.st_mode & S_IRWXU)); git_buf_free(&fullpath); #endif diff --git a/tests/checkout/crlf.c b/tests/checkout/crlf.c index 6b2c1b122..496f83d5d 100644 --- a/tests/checkout/crlf.c +++ b/tests/checkout/crlf.c @@ -79,10 +79,7 @@ void test_checkout_crlf__more_lf_autocrlf_true(void) git_checkout_head(g_repo, &opts); - if (GIT_EOL_NATIVE == GIT_EOL_LF) - check_file_contents("./crlf/more-lf", MORE_LF_TEXT_RAW); - else - check_file_contents("./crlf/more-lf", MORE_LF_TEXT_AS_CRLF); + check_file_contents("./crlf/more-lf", MORE_LF_TEXT_RAW); } void test_checkout_crlf__more_crlf_autocrlf_true(void) @@ -94,10 +91,7 @@ void test_checkout_crlf__more_crlf_autocrlf_true(void) git_checkout_head(g_repo, &opts); - if (GIT_EOL_NATIVE == GIT_EOL_LF) - check_file_contents("./crlf/more-crlf", MORE_CRLF_TEXT_RAW); - else - check_file_contents("./crlf/more-crlf", MORE_CRLF_TEXT_AS_CRLF); + check_file_contents("./crlf/more-crlf", MORE_CRLF_TEXT_RAW); } void test_checkout_crlf__all_crlf_autocrlf_true(void) @@ -285,8 +279,13 @@ void test_checkout_crlf__autocrlf_false_text_auto_attr(void) git_checkout_head(g_repo, &opts); - check_file_contents("./crlf/all-lf", ALL_LF_TEXT_RAW); - check_file_contents("./crlf/all-crlf", ALL_CRLF_TEXT_RAW); + if (GIT_EOL_NATIVE == GIT_EOL_CRLF) { + check_file_contents("./crlf/all-lf", ALL_LF_TEXT_AS_CRLF); + check_file_contents("./crlf/all-crlf", ALL_CRLF_TEXT_AS_CRLF); + } else { + check_file_contents("./crlf/all-lf", ALL_LF_TEXT_RAW); + check_file_contents("./crlf/all-crlf", ALL_CRLF_TEXT_RAW); + } } void test_checkout_crlf__autocrlf_true_text_auto_attr(void) diff --git a/tests/clar_libgit2.h b/tests/clar_libgit2.h index da37bd655..0744877cb 100644 --- a/tests/clar_libgit2.h +++ b/tests/clar_libgit2.h @@ -78,6 +78,24 @@ void clar__assert_equal_file( const char *file, int line); +GIT_INLINE(void) clar__assert_equal_oid( + const char *file, int line, const char *desc, + const git_oid *one, const git_oid *two) +{ + if (git_oid_cmp(one, two)) { + char err[] = "\"........................................\" != \"........................................\""; + + git_oid_fmt(&err[1], one); + git_oid_fmt(&err[47], two); + + clar__fail(file, line, desc, err, 1); + } +} + +#define cl_assert_equal_oid(one, two) \ + clar__assert_equal_oid(__FILE__, __LINE__, \ + "OID mismatch: " #one " != " #two, (one), (two)) + /* * Some utility macros for building long strings */ diff --git a/tests/clone/local.c b/tests/clone/local.c index a4406c1cc..c8ebc143d 100644 --- a/tests/clone/local.c +++ b/tests/clone/local.c @@ -31,31 +31,24 @@ void test_clone_local__should_clone_local(void) void test_clone_local__hardlinks(void) { git_repository *repo; - git_remote *remote; - git_signature *sig; + git_clone_options opts = GIT_CLONE_OPTIONS_INIT; git_buf buf = GIT_BUF_INIT; struct stat st; - /* * In this first clone, we just copy over, since the temp dir * will often be in a different filesystem, so we cannot * link. It also allows us to control the number of links */ - cl_git_pass(git_repository_init(&repo, "./clone.git", true)); - cl_git_pass(git_remote_create(&remote, repo, "origin", cl_fixture("testrepo.git"))); - cl_git_pass(git_signature_now(&sig, "foo", "bar")); - cl_git_pass(git_clone_local_into(repo, remote, NULL, NULL, false, sig)); - - git_remote_free(remote); + opts.bare = true; + opts.local = GIT_CLONE_LOCAL_NO_LINKS; + cl_git_pass(git_clone(&repo, cl_fixture("testrepo.git"), "./clone.git", &opts)); git_repository_free(repo); /* This second clone is in the same filesystem, so we can hardlink */ - cl_git_pass(git_repository_init(&repo, "./clone2.git", true)); - cl_git_pass(git_buf_puts(&buf, cl_git_path_url("clone.git"))); - cl_git_pass(git_remote_create(&remote, repo, "origin", buf.ptr)); - cl_git_pass(git_clone_local_into(repo, remote, NULL, NULL, true, sig)); + opts.local = GIT_CLONE_LOCAL; + cl_git_pass(git_clone(&repo, cl_git_path_url("clone.git"), "./clone2.git", &opts)); #ifndef GIT_WIN32 git_buf_clear(&buf); @@ -65,14 +58,11 @@ void test_clone_local__hardlinks(void) cl_assert_equal_i(2, st.st_nlink); #endif - git_remote_free(remote); git_repository_free(repo); git_buf_clear(&buf); - cl_git_pass(git_repository_init(&repo, "./clone3.git", true)); - cl_git_pass(git_buf_puts(&buf, cl_git_path_url("clone.git"))); - cl_git_pass(git_remote_create(&remote, repo, "origin", buf.ptr)); - cl_git_pass(git_clone_local_into(repo, remote, NULL, NULL, false, sig)); + opts.local = GIT_CLONE_LOCAL_NO_LINKS; + cl_git_pass(git_clone(&repo, cl_git_path_url("clone.git"), "./clone3.git", &opts)); git_buf_clear(&buf); cl_git_pass(git_buf_join_n(&buf, '/', 4, git_repository_path(repo), "objects", "08", "b041783f40edfe12bb406c9c9a8a040177c125")); @@ -80,7 +70,6 @@ void test_clone_local__hardlinks(void) cl_git_pass(p_stat(buf.ptr, &st)); cl_assert_equal_i(1, st.st_nlink); - git_remote_free(remote); git_repository_free(repo); /* this one should automatically use links */ @@ -95,7 +84,6 @@ void test_clone_local__hardlinks(void) #endif git_buf_free(&buf); - git_signature_free(sig); git_repository_free(repo); cl_git_pass(git_futils_rmdir_r("./clone.git", NULL, GIT_RMDIR_REMOVE_FILES)); diff --git a/tests/clone/nonetwork.c b/tests/clone/nonetwork.c index 4bdc6e13b..e9853313e 100644 --- a/tests/clone/nonetwork.c +++ b/tests/clone/nonetwork.c @@ -110,12 +110,25 @@ void test_clone_nonetwork__fail_with_already_existing_but_non_empty_directory(vo cl_git_fail(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); } +int custom_origin_name_remote_create( + git_remote **out, + git_repository *repo, + const char *name, + const char *url, + void *payload) +{ + GIT_UNUSED(name); + GIT_UNUSED(payload); + + return git_remote_create(out, repo, "my_origin", url); +} + void test_clone_nonetwork__custom_origin_name(void) { - g_options.remote_name = "my_origin"; - cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); + g_options.remote_cb = custom_origin_name_remote_create; + cl_git_pass(git_clone(&g_repo, cl_git_fixture_url("testrepo.git"), "./foo", &g_options)); - cl_git_pass(git_remote_load(&g_remote, g_repo, "my_origin")); + cl_git_pass(git_remote_load(&g_remote, g_repo, "my_origin")); } void test_clone_nonetwork__defaults(void) @@ -228,7 +241,7 @@ void test_clone_nonetwork__can_detached_head(void) cl_assert(git_repository_head_detached(cloned)); cl_git_pass(git_repository_head(&cloned_head, cloned)); - cl_assert(!git_oid_cmp(git_object_id(obj), git_reference_target(cloned_head))); + cl_assert_equal_oid(git_object_id(obj), git_reference_target(cloned_head)); cl_git_pass(git_reflog_read(&log, cloned, "HEAD")); entry = git_reflog_entry_byindex(log, 0); @@ -266,23 +279,6 @@ void test_clone_nonetwork__clone_updates_reflog_properly(void) assert_correct_reflog("refs/heads/master"); } -void test_clone_nonetwork__clone_into_updates_reflog_properly(void) -{ - git_remote *remote; - git_signature *sig; - cl_git_pass(git_signature_now(&sig, "Me", "foo@example.com")); - - cl_git_pass(git_repository_init(&g_repo, "./foo", false)); - cl_git_pass(git_remote_create(&remote, g_repo, "origin", cl_git_fixture_url("testrepo.git"))); - cl_git_pass(git_clone_into(g_repo, remote, NULL, NULL, sig)); - - assert_correct_reflog("HEAD"); - assert_correct_reflog("refs/heads/master"); - - git_remote_free(remote); - git_signature_free(sig); -} - static void cleanup_repository(void *path) { if (g_repo) { diff --git a/tests/clone/transport.c b/tests/clone/transport.c new file mode 100644 index 000000000..27568f228 --- /dev/null +++ b/tests/clone/transport.c @@ -0,0 +1,50 @@ +#include "clar_libgit2.h" + +#include "git2/clone.h" +#include "git2/transport.h" +#include "fileops.h" + +static int custom_transport( + git_transport **out, + git_remote *owner, + void *payload) +{ + *((int*)payload) = 1; + + return git_transport_local(out, owner, payload); +} + +static int custom_transport_remote_create( + git_remote **out, + git_repository *repo, + const char *name, + const char *url, + void *payload) +{ + int error; + + if ((error = git_remote_create(out, repo, name, url)) < 0) + return error; + + if ((error = git_remote_set_transport(*out, custom_transport, payload)) < 0) + return error; + + return 0; +} + +void test_clone_transport__custom_transport(void) +{ + git_repository *repo; + git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; + int custom_transport_used = 0; + + clone_opts.remote_cb = custom_transport_remote_create; + clone_opts.remote_cb_payload = &custom_transport_used; + + cl_git_pass(git_clone(&repo, cl_fixture("testrepo.git"), "./custom_transport.git", &clone_opts)); + git_repository_free(repo); + + cl_git_pass(git_futils_rmdir_r("./custom_transport.git", NULL, GIT_RMDIR_REMOVE_FILES)); + + cl_assert(custom_transport_used == 1); +} diff --git a/tests/commit/commit.c b/tests/commit/commit.c index fa181b703..f5461cfd3 100644 --- a/tests/commit/commit.c +++ b/tests/commit/commit.c @@ -43,7 +43,7 @@ void test_commit_commit__create_unexisting_update_ref(void) NULL, "some msg", tree, 1, (const git_commit **) &commit)); cl_git_pass(git_reference_lookup(&ref, _repo, "refs/heads/foo/bar")); - cl_assert(!git_oid_cmp(&oid, git_reference_target(ref))); + cl_assert_equal_oid(&oid, git_reference_target(ref)); git_tree_free(tree); git_commit_free(commit); diff --git a/tests/commit/write.c b/tests/commit/write.c index b1cdf4485..6212ef641 100644 --- a/tests/commit/write.c +++ b/tests/commit/write.c @@ -145,7 +145,7 @@ void test_commit_write__root(void) cl_assert(git_commit_parentcount(commit) == 0); cl_git_pass(git_reference_lookup(&branch, g_repo, branch_name)); branch_oid = git_reference_target(branch); - cl_git_pass(git_oid_cmp(branch_oid, &commit_id)); + cl_assert_equal_oid(branch_oid, &commit_id); cl_assert_equal_s(root_commit_message, git_commit_message(commit)); cl_git_pass(git_reflog_read(&log, g_repo, branch_name)); diff --git a/tests/core/buffer.c b/tests/core/buffer.c index da5ec605c..8310deae1 100644 --- a/tests/core/buffer.c +++ b/tests/core/buffer.c @@ -1034,18 +1034,14 @@ void test_core_buffer__lf_and_crlf_conversions(void) git_buf_sets(&src, "crlf\r\ncrlf\r\ncrlf\r\ncrlf\r\n"); - cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); - check_buf("crlf\r\ncrlf\r\ncrlf\r\ncrlf\r\n", tgt); - check_buf(src.ptr, tgt); + cl_git_fail_with(GIT_PASSTHROUGH, git_buf_text_lf_to_crlf(&tgt, &src)); cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); check_buf("crlf\ncrlf\ncrlf\ncrlf\n", tgt); git_buf_sets(&src, "\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf"); - cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); - check_buf("\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf", tgt); - check_buf(src.ptr, tgt); + cl_git_fail_with(GIT_PASSTHROUGH, git_buf_text_lf_to_crlf(&tgt, &src)); cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); check_buf("\ncrlf\ncrlf\ncrlf\ncrlf\ncrlf", tgt); @@ -1054,8 +1050,7 @@ void test_core_buffer__lf_and_crlf_conversions(void) git_buf_sets(&src, "\nlf\nlf\ncrlf\r\nlf\nlf\ncrlf\r\n"); - cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); - check_buf("\r\nlf\r\nlf\r\ncrlf\r\nlf\r\nlf\r\ncrlf\r\n", tgt); + cl_git_fail_with(GIT_PASSTHROUGH, git_buf_text_lf_to_crlf(&tgt, &src)); cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); check_buf("\nlf\nlf\ncrlf\nlf\nlf\ncrlf\n", tgt); @@ -1063,8 +1058,7 @@ void test_core_buffer__lf_and_crlf_conversions(void) git_buf_sets(&src, "\ncrlf\r\ncrlf\r\nlf\ncrlf\r\ncrlf"); - cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); - check_buf("\r\ncrlf\r\ncrlf\r\nlf\r\ncrlf\r\ncrlf", tgt); + cl_git_fail_with(GIT_PASSTHROUGH, git_buf_text_lf_to_crlf(&tgt, &src)); cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); check_buf("\ncrlf\ncrlf\nlf\ncrlf\ncrlf", tgt); @@ -1072,8 +1066,7 @@ void test_core_buffer__lf_and_crlf_conversions(void) git_buf_sets(&src, "\rcrlf\r\nlf\nlf\ncr\rcrlf\r\nlf\ncr\r"); - cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); - check_buf("\rcrlf\r\nlf\r\nlf\r\ncr\rcrlf\r\nlf\r\ncr\r", tgt); + cl_git_fail_with(GIT_PASSTHROUGH, git_buf_text_lf_to_crlf(&tgt, &src)); cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); check_buf("\rcrlf\nlf\nlf\ncr\rcrlf\nlf\ncr\r", tgt); @@ -1089,8 +1082,7 @@ void test_core_buffer__lf_and_crlf_conversions(void) /* blob correspondence tests */ git_buf_sets(&src, ALL_CRLF_TEXT_RAW); - cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); - check_buf(ALL_CRLF_TEXT_AS_CRLF, tgt); + cl_git_fail_with(GIT_PASSTHROUGH, git_buf_text_lf_to_crlf(&tgt, &src)); cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); check_buf(ALL_CRLF_TEXT_AS_LF, tgt); git_buf_free(&src); @@ -1105,16 +1097,14 @@ void test_core_buffer__lf_and_crlf_conversions(void) git_buf_free(&tgt); git_buf_sets(&src, MORE_CRLF_TEXT_RAW); - cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); - check_buf(MORE_CRLF_TEXT_AS_CRLF, tgt); + cl_git_fail_with(GIT_PASSTHROUGH, git_buf_text_lf_to_crlf(&tgt, &src)); cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); check_buf(MORE_CRLF_TEXT_AS_LF, tgt); git_buf_free(&src); git_buf_free(&tgt); git_buf_sets(&src, MORE_LF_TEXT_RAW); - cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src)); - check_buf(MORE_LF_TEXT_AS_CRLF, tgt); + cl_git_fail_with(GIT_PASSTHROUGH, git_buf_text_lf_to_crlf(&tgt, &src)); cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src)); check_buf(MORE_LF_TEXT_AS_LF, tgt); git_buf_free(&src); diff --git a/tests/core/pool.c b/tests/core/pool.c index 351d0c20f..a7ec8801b 100644 --- a/tests/core/pool.c +++ b/tests/core/pool.c @@ -38,19 +38,19 @@ void test_core_pool__1(void) cl_assert(git_pool_malloc(&p, i) != NULL); /* with fixed page size, allocation must end up with these values */ - cl_assert(git_pool__open_pages(&p) == 1); - cl_assert(git_pool__full_pages(&p) == 505); + cl_assert_equal_i(1, git_pool__open_pages(&p)); + cl_assert_equal_i(507, git_pool__full_pages(&p)); git_pool_clear(&p); - cl_git_pass(git_pool_init(&p, 1, 4100)); + cl_git_pass(git_pool_init(&p, 1, 4120)); for (i = 2010; i > 0; i--) cl_assert(git_pool_malloc(&p, i) != NULL); /* with fixed page size, allocation must end up with these values */ - cl_assert(git_pool__open_pages(&p) == 1); - cl_assert(git_pool__full_pages(&p) == 492); + cl_assert_equal_i(1, git_pool__open_pages(&p)); + cl_assert_equal_i(492, git_pool__full_pages(&p)); git_pool_clear(&p); } diff --git a/tests/diff/blob.c b/tests/diff/blob.c index 527007965..51bdbab15 100644 --- a/tests/diff/blob.c +++ b/tests/diff/blob.c @@ -137,9 +137,9 @@ static void assert_patch_matches_blobs( cl_assert(delta != NULL); cl_assert_equal_i(GIT_DELTA_MODIFIED, delta->status); - cl_assert(git_oid_equal(git_blob_id(a), &delta->old_file.id)); + cl_assert_equal_oid(git_blob_id(a), &delta->old_file.id); cl_assert_equal_sz(git_blob_rawsize(a), delta->old_file.size); - cl_assert(git_oid_equal(git_blob_id(b), &delta->new_file.id)); + cl_assert_equal_oid(git_blob_id(b), &delta->new_file.id); cl_assert_equal_sz(git_blob_rawsize(b), delta->new_file.size); cl_assert_equal_i(hunks, (int)git_patch_num_hunks(p)); @@ -274,7 +274,7 @@ void test_diff_blob__can_compare_against_null_blobs_with_patch(void) delta = git_patch_get_delta(p); cl_assert(delta != NULL); cl_assert_equal_i(GIT_DELTA_DELETED, delta->status); - cl_assert(git_oid_equal(git_blob_id(d), &delta->old_file.id)); + cl_assert_equal_oid(git_blob_id(d), &delta->old_file.id); cl_assert_equal_sz(git_blob_rawsize(d), delta->old_file.size); cl_assert(git_oid_iszero(&delta->new_file.id)); cl_assert_equal_sz(0, delta->new_file.size); @@ -301,7 +301,7 @@ void test_diff_blob__can_compare_against_null_blobs_with_patch(void) cl_assert_equal_i(GIT_DELTA_ADDED, delta->status); cl_assert(git_oid_iszero(&delta->old_file.id)); cl_assert_equal_sz(0, delta->old_file.size); - cl_assert(git_oid_equal(git_blob_id(d), &delta->new_file.id)); + cl_assert_equal_oid(git_blob_id(d), &delta->new_file.id); cl_assert_equal_sz(git_blob_rawsize(d), delta->new_file.size); cl_assert_equal_i(1, (int)git_patch_num_hunks(p)); @@ -392,9 +392,9 @@ void test_diff_blob__can_compare_identical_blobs_with_patch(void) cl_assert(delta != NULL); cl_assert_equal_i(GIT_DELTA_UNMODIFIED, delta->status); cl_assert_equal_sz(delta->old_file.size, git_blob_rawsize(d)); - cl_assert(git_oid_equal(git_blob_id(d), &delta->old_file.id)); + cl_assert_equal_oid(git_blob_id(d), &delta->old_file.id); cl_assert_equal_sz(delta->new_file.size, git_blob_rawsize(d)); - cl_assert(git_oid_equal(git_blob_id(d), &delta->new_file.id)); + cl_assert_equal_oid(git_blob_id(d), &delta->new_file.id); cl_assert_equal_i(0, (int)git_patch_num_hunks(p)); git_patch_free(p); diff --git a/tests/diff/iterator.c b/tests/diff/iterator.c index a2df1c7a7..26f670cfa 100644 --- a/tests/diff/iterator.c +++ b/tests/diff/iterator.c @@ -380,7 +380,7 @@ static void index_iterator_test( if (expected_oids != NULL) { git_oid oid; cl_git_pass(git_oid_fromstr(&oid, expected_oids[count])); - cl_assert_equal_i(git_oid_cmp(&oid, &entry->id), 0); + cl_assert_equal_oid(&oid, &entry->id); } count++; diff --git a/tests/fetchhead/nonetwork.c b/tests/fetchhead/nonetwork.c index e7ff2ca30..7b64a6339 100644 --- a/tests/fetchhead/nonetwork.c +++ b/tests/fetchhead/nonetwork.c @@ -120,7 +120,7 @@ static int fetchhead_ref_cb(const char *name, const char *url, expected = git_vector_get(cb_data->fetchhead_vector, cb_data->idx); - cl_assert(git_oid_cmp(&expected->oid, oid) == 0); + cl_assert_equal_oid(&expected->oid, oid); cl_assert(expected->is_merge == is_merge); if (expected->ref_name) @@ -174,7 +174,7 @@ static int read_old_style_cb(const char *name, const char *url, cl_assert(name == NULL); cl_assert(url == NULL); - cl_assert(git_oid_cmp(&expected, oid) == 0); + cl_assert_equal_oid(&expected, oid); cl_assert(is_merge == 1); return 0; @@ -201,7 +201,7 @@ static int read_type_missing(const char *ref_name, const char *remote_url, cl_assert_equal_s("name", ref_name); cl_assert_equal_s("remote_url", remote_url); - cl_assert(git_oid_cmp(&expected, oid) == 0); + cl_assert_equal_oid(&expected, oid); cl_assert(is_merge == 0); return 0; @@ -228,7 +228,7 @@ static int read_name_missing(const char *ref_name, const char *remote_url, cl_assert(ref_name == NULL); cl_assert_equal_s("remote_url", remote_url); - cl_assert(git_oid_cmp(&expected, oid) == 0); + cl_assert_equal_oid(&expected, oid); cl_assert(is_merge == 0); return 0; diff --git a/tests/index/conflicts.c b/tests/index/conflicts.c index 90aaa442d..427351693 100644 --- a/tests/index/conflicts.c +++ b/tests/index/conflicts.c @@ -107,13 +107,13 @@ void test_index_conflicts__get(void) cl_assert_equal_s("conflicts-one.txt", conflict_entry[0]->path); git_oid_fromstr(&oid, CONFLICTS_ONE_ANCESTOR_OID); - cl_assert(git_oid_cmp(&conflict_entry[0]->id, &oid) == 0); + cl_assert_equal_oid(&oid, &conflict_entry[0]->id); git_oid_fromstr(&oid, CONFLICTS_ONE_OUR_OID); - cl_assert(git_oid_cmp(&conflict_entry[1]->id, &oid) == 0); + cl_assert_equal_oid(&oid, &conflict_entry[1]->id); git_oid_fromstr(&oid, CONFLICTS_ONE_THEIR_OID); - cl_assert(git_oid_cmp(&conflict_entry[2]->id, &oid) == 0); + cl_assert_equal_oid(&oid, &conflict_entry[2]->id); cl_git_pass(git_index_conflict_get(&conflict_entry[0], &conflict_entry[1], &conflict_entry[2], repo_index, "conflicts-two.txt")); @@ -121,13 +121,13 @@ void test_index_conflicts__get(void) cl_assert_equal_s("conflicts-two.txt", conflict_entry[0]->path); git_oid_fromstr(&oid, CONFLICTS_TWO_ANCESTOR_OID); - cl_assert(git_oid_cmp(&conflict_entry[0]->id, &oid) == 0); + cl_assert_equal_oid(&oid, &conflict_entry[0]->id); git_oid_fromstr(&oid, CONFLICTS_TWO_OUR_OID); - cl_assert(git_oid_cmp(&conflict_entry[1]->id, &oid) == 0); + cl_assert_equal_oid(&oid, &conflict_entry[1]->id); git_oid_fromstr(&oid, CONFLICTS_TWO_THEIR_OID); - cl_assert(git_oid_cmp(&conflict_entry[2]->id, &oid) == 0); + cl_assert_equal_oid(&oid, &conflict_entry[2]->id); } void test_index_conflicts__iterate(void) @@ -141,29 +141,29 @@ void test_index_conflicts__iterate(void) cl_git_pass(git_index_conflict_next(&conflict_entry[0], &conflict_entry[1], &conflict_entry[2], iterator)); git_oid_fromstr(&oid, CONFLICTS_ONE_ANCESTOR_OID); - cl_assert(git_oid_cmp(&conflict_entry[0]->id, &oid) == 0); + cl_assert_equal_oid(&oid, &conflict_entry[0]->id); cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-one.txt") == 0); git_oid_fromstr(&oid, CONFLICTS_ONE_OUR_OID); - cl_assert(git_oid_cmp(&conflict_entry[1]->id, &oid) == 0); + cl_assert_equal_oid(&oid, &conflict_entry[1]->id); cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-one.txt") == 0); git_oid_fromstr(&oid, CONFLICTS_ONE_THEIR_OID); - cl_assert(git_oid_cmp(&conflict_entry[2]->id, &oid) == 0); + cl_assert_equal_oid(&oid, &conflict_entry[2]->id); cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-one.txt") == 0); cl_git_pass(git_index_conflict_next(&conflict_entry[0], &conflict_entry[1], &conflict_entry[2], iterator)); git_oid_fromstr(&oid, CONFLICTS_TWO_ANCESTOR_OID); - cl_assert(git_oid_cmp(&conflict_entry[0]->id, &oid) == 0); + cl_assert_equal_oid(&oid, &conflict_entry[0]->id); cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-two.txt") == 0); git_oid_fromstr(&oid, CONFLICTS_TWO_OUR_OID); - cl_assert(git_oid_cmp(&conflict_entry[1]->id, &oid) == 0); + cl_assert_equal_oid(&oid, &conflict_entry[1]->id); cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-two.txt") == 0); git_oid_fromstr(&oid, CONFLICTS_TWO_THEIR_OID); - cl_assert(git_oid_cmp(&conflict_entry[2]->id, &oid) == 0); + cl_assert_equal_oid(&oid, &conflict_entry[2]->id); cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-two.txt") == 0); cl_assert(git_index_conflict_next(&conflict_entry[0], &conflict_entry[1], &conflict_entry[2], iterator) == GIT_ITEROVER); @@ -281,7 +281,7 @@ void test_index_conflicts__partial(void) cl_git_pass(git_index_conflict_get(&conflict_entry[0], &conflict_entry[1], &conflict_entry[2], repo_index, "test-one.txt")); - cl_assert(git_oid_cmp(&ancestor_entry.id, &conflict_entry[0]->id) == 0); + cl_assert_equal_oid(&ancestor_entry.id, &conflict_entry[0]->id); cl_assert(conflict_entry[1] == NULL); cl_assert(conflict_entry[2] == NULL); } diff --git a/tests/index/crlf.c b/tests/index/crlf.c index 7babd5939..23f47932f 100644 --- a/tests/index/crlf.c +++ b/tests/index/crlf.c @@ -41,7 +41,7 @@ void test_index_crlf__autocrlf_false_no_attrs(void) cl_git_pass(git_oid_fromstr(&oid, (GIT_EOL_NATIVE == GIT_EOL_CRLF) ? FILE_OID_CRLF : FILE_OID_LF)); - cl_assert(git_oid_cmp(&oid, &entry->id) == 0); + cl_assert_equal_oid(&oid, &entry->id); } void test_index_crlf__autocrlf_true_no_attrs(void) @@ -58,7 +58,7 @@ void test_index_crlf__autocrlf_true_no_attrs(void) entry = git_index_get_bypath(g_index, "newfile.txt", 0); cl_git_pass(git_oid_fromstr(&oid, FILE_OID_LF)); - cl_assert(git_oid_cmp(&oid, &entry->id) == 0); + cl_assert_equal_oid(&oid, &entry->id); } void test_index_crlf__autocrlf_input_no_attrs(void) @@ -75,7 +75,7 @@ void test_index_crlf__autocrlf_input_no_attrs(void) entry = git_index_get_bypath(g_index, "newfile.txt", 0); cl_git_pass(git_oid_fromstr(&oid, FILE_OID_LF)); - cl_assert(git_oid_cmp(&oid, &entry->id) == 0); + cl_assert_equal_oid(&oid, &entry->id); } void test_index_crlf__autocrlf_false_text_auto_attr(void) @@ -94,7 +94,7 @@ void test_index_crlf__autocrlf_false_text_auto_attr(void) entry = git_index_get_bypath(g_index, "newfile.txt", 0); cl_git_pass(git_oid_fromstr(&oid, FILE_OID_LF)); - cl_assert(git_oid_cmp(&oid, &entry->id) == 0); + cl_assert_equal_oid(&oid, &entry->id); } void test_index_crlf__autocrlf_true_text_auto_attr(void) @@ -113,7 +113,7 @@ void test_index_crlf__autocrlf_true_text_auto_attr(void) entry = git_index_get_bypath(g_index, "newfile.txt", 0); cl_git_pass(git_oid_fromstr(&oid, FILE_OID_LF)); - cl_assert(git_oid_cmp(&oid, &entry->id) == 0); + cl_assert_equal_oid(&oid, &entry->id); } void test_index_crlf__autocrlf_input_text_auto_attr(void) @@ -132,7 +132,7 @@ void test_index_crlf__autocrlf_input_text_auto_attr(void) entry = git_index_get_bypath(g_index, "newfile.txt", 0); cl_git_pass(git_oid_fromstr(&oid, FILE_OID_LF)); - cl_assert(git_oid_cmp(&oid, &entry->id) == 0); + cl_assert_equal_oid(&oid, &entry->id); } void test_index_crlf__safecrlf_true_no_attrs(void) diff --git a/tests/index/read_tree.c b/tests/index/read_tree.c index 6c6b40121..0e1882818 100644 --- a/tests/index/read_tree.c +++ b/tests/index/read_tree.c @@ -37,7 +37,7 @@ void test_index_read_tree__read_write_involution(void) git_tree_free(tree); cl_git_pass(git_index_write_tree(&tree_oid, index)); - cl_assert(git_oid_cmp(&expected, &tree_oid) == 0); + cl_assert_equal_oid(&expected, &tree_oid); git_index_free(index); git_repository_free(repo); diff --git a/tests/index/rename.c b/tests/index/rename.c index b6fb61d10..dd3cfa732 100644 --- a/tests/index/rename.c +++ b/tests/index/rename.c @@ -27,7 +27,7 @@ void test_index_rename__single_file(void) cl_assert(!git_index_find(&position, index, "lame.name.txt")); entry = git_index_get_byindex(index, position); - cl_assert(git_oid_cmp(&expected, &entry->id) == 0); + cl_assert_equal_oid(&expected, &entry->id); /* This removes the entry from the index, but not from the object database */ cl_git_pass(git_index_remove(index, "lame.name.txt", 0)); @@ -41,7 +41,7 @@ void test_index_rename__single_file(void) cl_assert(!git_index_find(&position, index, "fancy.name.txt")); entry = git_index_get_byindex(index, position); - cl_assert(git_oid_cmp(&expected, &entry->id) == 0); + cl_assert_equal_oid(&expected, &entry->id); git_index_free(index); git_repository_free(repo); diff --git a/tests/index/reuc.c b/tests/index/reuc.c index 27240a30f..0b4d71a6a 100644 --- a/tests/index/reuc.c +++ b/tests/index/reuc.c @@ -53,9 +53,9 @@ void test_index_reuc__add(void) cl_assert(reuc->mode[0] == 0100644); cl_assert(reuc->mode[1] == 0100644); cl_assert(reuc->mode[2] == 0100644); - cl_assert(git_oid_cmp(&reuc->oid[0], &ancestor_oid) == 0); - cl_assert(git_oid_cmp(&reuc->oid[1], &our_oid) == 0); - cl_assert(git_oid_cmp(&reuc->oid[2], &their_oid) == 0); + cl_assert_equal_oid(&reuc->oid[0], &ancestor_oid); + cl_assert_equal_oid(&reuc->oid[1], &our_oid); + cl_assert_equal_oid(&reuc->oid[2], &their_oid); } void test_index_reuc__add_no_ancestor(void) @@ -78,9 +78,9 @@ void test_index_reuc__add_no_ancestor(void) cl_assert(reuc->mode[0] == 0); cl_assert(reuc->mode[1] == 0100644); cl_assert(reuc->mode[2] == 0100644); - cl_assert(git_oid_cmp(&reuc->oid[0], &ancestor_oid) == 0); - cl_assert(git_oid_cmp(&reuc->oid[1], &our_oid) == 0); - cl_assert(git_oid_cmp(&reuc->oid[2], &their_oid) == 0); + cl_assert_equal_oid(&reuc->oid[0], &ancestor_oid); + cl_assert_equal_oid(&reuc->oid[1], &our_oid); + cl_assert_equal_oid(&reuc->oid[2], &their_oid); } void test_index_reuc__read_bypath(void) @@ -97,11 +97,11 @@ void test_index_reuc__read_bypath(void) cl_assert(reuc->mode[1] == 0100644); cl_assert(reuc->mode[2] == 0100644); git_oid_fromstr(&oid, TWO_ANCESTOR_OID); - cl_assert(git_oid_cmp(&reuc->oid[0], &oid) == 0); + cl_assert_equal_oid(&reuc->oid[0], &oid); git_oid_fromstr(&oid, TWO_OUR_OID); - cl_assert(git_oid_cmp(&reuc->oid[1], &oid) == 0); + cl_assert_equal_oid(&reuc->oid[1], &oid); git_oid_fromstr(&oid, TWO_THEIR_OID); - cl_assert(git_oid_cmp(&reuc->oid[2], &oid) == 0); + cl_assert_equal_oid(&reuc->oid[2], &oid); cl_assert(reuc = git_index_reuc_get_bypath(repo_index, "one.txt")); @@ -110,11 +110,11 @@ void test_index_reuc__read_bypath(void) cl_assert(reuc->mode[1] == 0100644); cl_assert(reuc->mode[2] == 0100644); git_oid_fromstr(&oid, ONE_ANCESTOR_OID); - cl_assert(git_oid_cmp(&reuc->oid[0], &oid) == 0); + cl_assert_equal_oid(&reuc->oid[0], &oid); git_oid_fromstr(&oid, ONE_OUR_OID); - cl_assert(git_oid_cmp(&reuc->oid[1], &oid) == 0); + cl_assert_equal_oid(&reuc->oid[1], &oid); git_oid_fromstr(&oid, ONE_THEIR_OID); - cl_assert(git_oid_cmp(&reuc->oid[2], &oid) == 0); + cl_assert_equal_oid(&reuc->oid[2], &oid); } void test_index_reuc__ignore_case(void) @@ -142,11 +142,11 @@ void test_index_reuc__ignore_case(void) cl_assert(reuc->mode[1] == 0100644); cl_assert(reuc->mode[2] == 0100644); git_oid_fromstr(&oid, TWO_ANCESTOR_OID); - cl_assert(git_oid_cmp(&reuc->oid[0], &oid) == 0); + cl_assert_equal_oid(&reuc->oid[0], &oid); git_oid_fromstr(&oid, TWO_OUR_OID); - cl_assert(git_oid_cmp(&reuc->oid[1], &oid) == 0); + cl_assert_equal_oid(&reuc->oid[1], &oid); git_oid_fromstr(&oid, TWO_THEIR_OID); - cl_assert(git_oid_cmp(&reuc->oid[2], &oid) == 0); + cl_assert_equal_oid(&reuc->oid[2], &oid); } void test_index_reuc__read_byindex(void) @@ -163,11 +163,11 @@ void test_index_reuc__read_byindex(void) cl_assert(reuc->mode[1] == 0100644); cl_assert(reuc->mode[2] == 0100644); git_oid_fromstr(&oid, ONE_ANCESTOR_OID); - cl_assert(git_oid_cmp(&reuc->oid[0], &oid) == 0); + cl_assert_equal_oid(&reuc->oid[0], &oid); git_oid_fromstr(&oid, ONE_OUR_OID); - cl_assert(git_oid_cmp(&reuc->oid[1], &oid) == 0); + cl_assert_equal_oid(&reuc->oid[1], &oid); git_oid_fromstr(&oid, ONE_THEIR_OID); - cl_assert(git_oid_cmp(&reuc->oid[2], &oid) == 0); + cl_assert_equal_oid(&reuc->oid[2], &oid); cl_assert(reuc = git_index_reuc_get_byindex(repo_index, 1)); @@ -176,11 +176,11 @@ void test_index_reuc__read_byindex(void) cl_assert(reuc->mode[1] == 0100644); cl_assert(reuc->mode[2] == 0100644); git_oid_fromstr(&oid, TWO_ANCESTOR_OID); - cl_assert(git_oid_cmp(&reuc->oid[0], &oid) == 0); + cl_assert_equal_oid(&reuc->oid[0], &oid); git_oid_fromstr(&oid, TWO_OUR_OID); - cl_assert(git_oid_cmp(&reuc->oid[1], &oid) == 0); + cl_assert_equal_oid(&reuc->oid[1], &oid); git_oid_fromstr(&oid, TWO_THEIR_OID); - cl_assert(git_oid_cmp(&reuc->oid[2], &oid) == 0); + cl_assert_equal_oid(&reuc->oid[2], &oid); } void test_index_reuc__updates_existing(void) @@ -216,11 +216,11 @@ void test_index_reuc__updates_existing(void) cl_assert_equal_s("TWO.txt", reuc->path); git_oid_fromstr(&oid, TWO_OUR_OID); - cl_assert(git_oid_cmp(&reuc->oid[0], &oid) == 0); + cl_assert_equal_oid(&reuc->oid[0], &oid); git_oid_fromstr(&oid, TWO_THEIR_OID); - cl_assert(git_oid_cmp(&reuc->oid[1], &oid) == 0); + cl_assert_equal_oid(&reuc->oid[1], &oid); git_oid_fromstr(&oid, TWO_ANCESTOR_OID); - cl_assert(git_oid_cmp(&reuc->oid[2], &oid) == 0); + cl_assert_equal_oid(&reuc->oid[2], &oid); } void test_index_reuc__remove(void) @@ -242,11 +242,11 @@ void test_index_reuc__remove(void) cl_assert(reuc->mode[1] == 0100644); cl_assert(reuc->mode[2] == 0100644); git_oid_fromstr(&oid, TWO_ANCESTOR_OID); - cl_assert(git_oid_cmp(&reuc->oid[0], &oid) == 0); + cl_assert_equal_oid(&reuc->oid[0], &oid); git_oid_fromstr(&oid, TWO_OUR_OID); - cl_assert(git_oid_cmp(&reuc->oid[1], &oid) == 0); + cl_assert_equal_oid(&reuc->oid[1], &oid); git_oid_fromstr(&oid, TWO_THEIR_OID); - cl_assert(git_oid_cmp(&reuc->oid[2], &oid) == 0); + cl_assert_equal_oid(&reuc->oid[2], &oid); } void test_index_reuc__write(void) diff --git a/tests/index/tests.c b/tests/index/tests.c index fa5c0bb1a..373889912 100644 --- a/tests/index/tests.c +++ b/tests/index/tests.c @@ -243,11 +243,11 @@ void test_index_tests__add(void) entry = git_index_get_byindex(index, 0); /* And the built-in hashing mechanism worked as expected */ - cl_assert(git_oid_cmp(&id1, &entry->id) == 0); + cl_assert_equal_oid(&id1, &entry->id); /* Test access by path instead of index */ cl_assert((entry = git_index_get_bypath(index, "test.txt", 0)) != NULL); - cl_assert(git_oid_cmp(&id1, &entry->id) == 0); + cl_assert_equal_oid(&id1, &entry->id); git_index_free(index); git_repository_free(repo); @@ -283,14 +283,14 @@ void test_index_tests__add_issue_1397(void) /* Make sure the initial SHA-1 is correct */ cl_assert((entry = git_index_get_bypath(index, "crlf_file.txt", 0)) != NULL); - cl_assert_(git_oid_cmp(&id1, &entry->id) == 0, "first oid check"); + cl_assert_equal_oid(&id1, &entry->id); /* Update the index */ cl_git_pass(git_index_add_bypath(index, "crlf_file.txt")); /* Check the new SHA-1 */ cl_assert((entry = git_index_get_bypath(index, "crlf_file.txt", 0)) != NULL); - cl_assert_(git_oid_cmp(&id1, &entry->id) == 0, "second oid check"); + cl_assert_equal_oid(&id1, &entry->id); git_index_free(index); } diff --git a/tests/merge/trees/trivial.c b/tests/merge/trees/trivial.c index 62a4574b8..55f38248f 100644 --- a/tests/merge/trees/trivial.c +++ b/tests/merge/trees/trivial.c @@ -259,7 +259,7 @@ void test_merge_trees_trivial__13(void) cl_assert(entry = git_index_get_bypath(result, "modified-in-13.txt", 0)); cl_git_pass(git_oid_fromstr(&expected_oid, "1cff9ec6a47a537380dedfdd17c9e76d74259a2b")); - cl_assert(git_oid_cmp(&entry->id, &expected_oid) == 0); + cl_assert_equal_oid(&expected_oid, &entry->id); cl_assert(git_index_reuc_entrycount(result) == 0); cl_assert(merge_trivial_conflict_entrycount(result) == 0); diff --git a/tests/merge/workdir/dirty.c b/tests/merge/workdir/dirty.c index 776e4ea69..2f776853e 100644 --- a/tests/merge/workdir/dirty.c +++ b/tests/merge/workdir/dirty.c @@ -97,7 +97,7 @@ static int merge_branch(void) cl_git_pass(git_oid_fromstr(&their_oids[0], MERGE_BRANCH_OID)); cl_git_pass(git_merge_head_from_id(&their_heads[0], repo, &their_oids[0])); - checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_ALLOW_CONFLICTS; + checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; error = git_merge(repo, (const git_merge_head **)their_heads, 1, &merge_opts, &checkout_opts); git_merge_head_free(their_heads[0]); diff --git a/tests/network/fetchlocal.c b/tests/network/fetchlocal.c index 0d23bef48..8809f427d 100644 --- a/tests/network/fetchlocal.c +++ b/tests/network/fetchlocal.c @@ -87,28 +87,43 @@ void test_network_fetchlocal__partial(void) git_remote_free(origin); } -void test_network_fetchlocal__clone_into_mirror(void) +static int remote_mirror_cb(git_remote **out, git_repository *repo, + const char *name, const char *url, void *payload) { - git_buf path = GIT_BUF_INIT; - git_repository *repo; + int error; git_remote *remote; - git_reference *head; - cl_git_pass(git_repository_init(&repo, "./foo.git", true)); - cl_git_pass(git_remote_create(&remote, repo, "origin", cl_git_fixture_url("testrepo.git"))); + GIT_UNUSED(payload); + + if ((error = git_remote_create(&remote, repo, name, url)) < 0) + return error; git_remote_clear_refspecs(remote); - cl_git_pass(git_remote_add_fetch(remote, "+refs/*:refs/*")); - cl_git_pass(git_clone_into(repo, remote, NULL, NULL, NULL)); + if ((error = git_remote_add_fetch(remote, "+refs/*:refs/*")) < 0) { + git_remote_free(remote); + return error; + } + + *out = remote; + return 0; +} + +void test_network_fetchlocal__clone_into_mirror(void) +{ + git_clone_options opts = GIT_CLONE_OPTIONS_INIT; + git_repository *repo; + git_reference *head; + + opts.bare = true; + opts.remote_cb = remote_mirror_cb; + cl_git_pass(git_clone(&repo, cl_git_fixture_url("testrepo.git"), "./foo.git", &opts)); cl_git_pass(git_reference_lookup(&head, repo, "HEAD")); cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head)); cl_assert_equal_s("refs/heads/master", git_reference_symbolic_target(head)); - git_remote_free(remote); git_reference_free(head); git_repository_free(repo); - git_buf_free(&path); cl_fixture_cleanup("./foo.git"); } diff --git a/tests/network/remote/remotes.c b/tests/network/remote/remotes.c index 333b52a5b..21c57119a 100644 --- a/tests/network/remote/remotes.c +++ b/tests/network/remote/remotes.c @@ -72,18 +72,17 @@ void test_network_remote_remotes__error_when_not_found(void) void test_network_remote_remotes__error_when_no_push_available(void) { git_remote *r; - git_transport *t; git_push *p; cl_git_pass(git_remote_create_anonymous(&r, _repo, cl_fixture("testrepo.git"), NULL)); - cl_git_pass(git_transport_local(&t,r,NULL)); + cl_git_pass(git_remote_set_transport(r, git_transport_local, NULL)); + + cl_git_pass(git_remote_connect(r, GIT_DIRECTION_PUSH)); /* Make sure that push is really not available */ - t->push = NULL; - cl_git_pass(git_remote_set_transport(r, t)); + r->transport->push = NULL; - cl_git_pass(git_remote_connect(r, GIT_DIRECTION_PUSH)); cl_git_pass(git_push_new(&p, r)); cl_git_pass(git_push_add_refspec(p, "refs/heads/master")); cl_git_fail_with(git_push_finish(p), GIT_ERROR); @@ -438,27 +437,6 @@ void test_network_remote_remotes__returns_ENOTFOUND_when_neither_url_nor_pushurl git_remote_load(&remote, _repo, "no-remote-url"), GIT_ENOTFOUND); } -void test_network_remote_remotes__check_structure_version(void) -{ - git_transport transport = GIT_TRANSPORT_INIT; - const git_error *err; - - git_remote_free(_remote); - _remote = NULL; - cl_git_pass(git_remote_create_anonymous(&_remote, _repo, "test-protocol://localhost", NULL)); - - transport.version = 0; - cl_git_fail(git_remote_set_transport(_remote, &transport)); - err = giterr_last(); - cl_assert_equal_i(GITERR_INVALID, err->klass); - - giterr_clear(); - transport.version = 1024; - cl_git_fail(git_remote_set_transport(_remote, &transport)); - err = giterr_last(); - cl_assert_equal_i(GITERR_INVALID, err->klass); -} - void assert_cannot_create_remote(const char *name, int expected_error) { git_remote *remote = NULL; diff --git a/tests/notes/notes.c b/tests/notes/notes.c index e48d9df0e..8b1b57866 100644 --- a/tests/notes/notes.c +++ b/tests/notes/notes.c @@ -21,7 +21,7 @@ static void assert_note_equal(git_note *note, char *message, git_oid *note_oid) git_blob *blob; cl_assert_equal_s(git_note_message(note), message); - cl_assert(!git_oid_cmp(git_note_id(note), note_oid)); + cl_assert_equal_oid(git_note_id(note), note_oid); cl_git_pass(git_blob_lookup(&blob, _repo, note_oid)); cl_assert_equal_s(git_note_message(note), (const char *)git_blob_rawcontent(blob)); @@ -61,10 +61,10 @@ static int note_list_cb( cl_assert(*count < EXPECTATIONS_COUNT); cl_git_pass(git_oid_fromstr(&expected_note_oid, list_expectations[*count].note_sha)); - cl_assert(git_oid_cmp(&expected_note_oid, blob_id) == 0); + cl_assert_equal_oid(&expected_note_oid, blob_id); cl_git_pass(git_oid_fromstr(&expected_target_oid, list_expectations[*count].annotated_object_sha)); - cl_assert(git_oid_cmp(&expected_target_oid, annotated_obj_id) == 0); + cl_assert_equal_oid(&expected_target_oid, annotated_obj_id); (*count)++; @@ -290,7 +290,7 @@ void test_notes_notes__can_read_a_note_in_an_existing_fanout(void) cl_git_pass(git_note_read(¬e, _repo, "refs/notes/fanout", &target_oid)); cl_git_pass(git_oid_fromstr(¬e_oid, "08b041783f40edfe12bb406c9c9a8a040177c125")); - cl_assert(!git_oid_cmp(git_note_id(note), ¬e_oid)); + cl_assert_equal_oid(git_note_id(note), ¬e_oid); git_note_free(note); } diff --git a/tests/notes/notesref.c b/tests/notes/notesref.c index a33141979..a59af209c 100644 --- a/tests/notes/notesref.c +++ b/tests/notes/notesref.c @@ -46,13 +46,13 @@ void test_notes_notesref__config_corenotesref(void) cl_git_pass(git_note_read(&_note, _repo, NULL, &oid)); cl_assert_equal_s("test123test\n", git_note_message(_note)); - cl_assert(!git_oid_cmp(git_note_id(_note), ¬e_oid)); + cl_assert_equal_oid(git_note_id(_note), ¬e_oid); git_note_free(_note); cl_git_pass(git_note_read(&_note, _repo, "refs/notes/mydefaultnotesref", &oid)); cl_assert_equal_s("test123test\n", git_note_message(_note)); - cl_assert(!git_oid_cmp(git_note_id(_note), ¬e_oid)); + cl_assert_equal_oid(git_note_id(_note), ¬e_oid); cl_git_pass(git_note_default_ref(&default_ref, _repo)); cl_assert_equal_s("refs/notes/mydefaultnotesref", default_ref); diff --git a/tests/object/lookupbypath.c b/tests/object/lookupbypath.c index 31aac7647..13cd6a128 100644 --- a/tests/object/lookupbypath.c +++ b/tests/object/lookupbypath.c @@ -52,16 +52,16 @@ void test_object_lookupbypath__from_root_tree(void) { cl_git_pass(git_object_lookup_bypath(&g_actualobject, (git_object*)g_root_tree, "subdir/subdir_test2.txt", GIT_OBJ_BLOB)); - cl_assert_equal_i(0, git_oid_cmp(git_object_id(g_expectedobject), - git_object_id(g_actualobject))); + cl_assert_equal_oid(git_object_id(g_expectedobject), + git_object_id(g_actualobject)); } void test_object_lookupbypath__from_head_commit(void) { cl_git_pass(git_object_lookup_bypath(&g_actualobject, (git_object*)g_head_commit, "subdir/subdir_test2.txt", GIT_OBJ_BLOB)); - cl_assert_equal_i(0, git_oid_cmp(git_object_id(g_expectedobject), - git_object_id(g_actualobject))); + cl_assert_equal_oid(git_object_id(g_expectedobject), + git_object_id(g_actualobject)); } void test_object_lookupbypath__from_subdir_tree(void) @@ -74,8 +74,8 @@ void test_object_lookupbypath__from_subdir_tree(void) cl_git_pass(git_object_lookup_bypath(&g_actualobject, (git_object*)tree, "subdir_test2.txt", GIT_OBJ_BLOB)); - cl_assert_equal_i(0, git_oid_cmp(git_object_id(g_expectedobject), - git_object_id(g_actualobject))); + cl_assert_equal_oid(git_object_id(g_expectedobject), + git_object_id(g_actualobject)); git_tree_entry_free(entry); git_tree_free(tree); diff --git a/tests/object/peel.c b/tests/object/peel.c index b6c9c7a3b..6310388c4 100644 --- a/tests/object/peel.c +++ b/tests/object/peel.c @@ -29,7 +29,7 @@ static void assert_peel( cl_git_pass(git_object_peel(&peeled, obj, requested_type)); cl_git_pass(git_oid_fromstr(&expected_oid, expected_sha)); - cl_assert_equal_i(0, git_oid_cmp(&expected_oid, git_object_id(peeled))); + cl_assert_equal_oid(&expected_oid, git_object_id(peeled)); cl_assert_equal_i(expected_type, git_object_type(peeled)); diff --git a/tests/object/tree/write.c b/tests/object/tree/write.c index 45356e807..ddb62e278 100644 --- a/tests/object/tree/write.c +++ b/tests/object/tree/write.c @@ -104,6 +104,7 @@ void test_object_tree_write__subtree(void) void test_object_tree_write__sorted_subtrees(void) { git_treebuilder *builder; + git_tree *tree; unsigned int i; int position_c = -1, position_cake = -1, position_config = -1; @@ -143,8 +144,9 @@ void test_object_tree_write__sorted_subtrees(void) cl_git_pass(git_treebuilder_write(&tree_oid, g_repo, builder)); - for (i = 0; i < builder->entries.length; ++i) { - git_tree_entry *entry = git_vector_get(&builder->entries, i); + cl_git_pass(git_tree_lookup(&tree, g_repo, &tree_oid)); + for (i = 0; i < git_tree_entrycount(tree); i++) { + const git_tree_entry *entry = git_tree_entry_byindex(tree, i); if (strcmp(entry->filename, "c") == 0) position_c = i; @@ -156,6 +158,8 @@ void test_object_tree_write__sorted_subtrees(void) position_config = i; } + git_tree_free(tree); + cl_assert(position_c != -1); cl_assert(position_cake != -1); cl_assert(position_config != -1); diff --git a/tests/odb/mixed.c b/tests/odb/mixed.c index ceba4ec81..2dad4b64e 100644 --- a/tests/odb/mixed.c +++ b/tests/odb/mixed.c @@ -58,7 +58,7 @@ void test_odb_mixed__dup_oid_prefix_0(void) { cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex))); cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex))); cl_git_pass(git_odb_exists_prefix(&found, _odb, &oid, strlen(hex))); - cl_assert(git_oid_equal(&found, git_odb_object_id(obj))); + cl_assert_equal_oid(&found, git_odb_object_id(obj)); git_odb_object_free(obj); strncpy(hex, "dea509d0b", sizeof(hex)); @@ -79,7 +79,7 @@ void test_odb_mixed__dup_oid_prefix_0(void) { cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex))); cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex))); cl_git_pass(git_odb_exists_prefix(&found, _odb, &oid, strlen(hex))); - cl_assert(git_oid_equal(&found, git_odb_object_id(obj))); + cl_assert_equal_oid(&found, git_odb_object_id(obj)); git_odb_object_free(obj); strncpy(hex, "81b5bff5f", sizeof(hex)); @@ -100,7 +100,7 @@ void test_odb_mixed__dup_oid_prefix_0(void) { cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex))); cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex))); cl_git_pass(git_odb_exists_prefix(&found, _odb, &oid, strlen(hex))); - cl_assert(git_oid_equal(&found, git_odb_object_id(obj))); + cl_assert_equal_oid(&found, git_odb_object_id(obj)); git_odb_object_free(obj); strncpy(hex, "0ddeadede", sizeof(hex)); diff --git a/tests/online/clone.c b/tests/online/clone.c index 4f4312a8c..2e2e97675 100644 --- a/tests/online/clone.c +++ b/tests/online/clone.c @@ -124,65 +124,49 @@ void test_online_clone__can_checkout_a_cloned_repo(void) git_buf_free(&path); } -void test_online_clone__clone_into(void) +static int remote_mirror_cb(git_remote **out, git_repository *repo, + const char *name, const char *url, void *payload) { - git_buf path = GIT_BUF_INIT; + int error; git_remote *remote; - git_reference *head; - git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; - git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; - - bool checkout_progress_cb_was_called = false, - fetch_progress_cb_was_called = false; - - checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE; - checkout_opts.progress_cb = &checkout_progress; - checkout_opts.progress_payload = &checkout_progress_cb_was_called; + git_remote_callbacks *callbacks = (git_remote_callbacks *) payload; - cl_git_pass(git_repository_init(&g_repo, "./foo", false)); - cl_git_pass(git_remote_create(&remote, g_repo, "origin", LIVE_REPO_URL)); - callbacks.transfer_progress = &fetch_progress; - callbacks.payload = &fetch_progress_cb_was_called; - git_remote_set_callbacks(remote, &callbacks); + if ((error = git_remote_create(&remote, repo, name, url)) < 0) + return error; - cl_git_pass(git_clone_into(g_repo, remote, &checkout_opts, NULL, NULL)); - - cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "master.txt")); - cl_assert_equal_i(true, git_path_isfile(git_buf_cstr(&path))); + if ((error = git_remote_set_callbacks(remote, callbacks)) < 0) { + git_remote_free(remote); + return error; + } - cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD")); - cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head)); - cl_assert_equal_s("refs/heads/master", git_reference_symbolic_target(head)); + git_remote_clear_refspecs(remote); - cl_assert_equal_i(true, checkout_progress_cb_was_called); - cl_assert_equal_i(true, fetch_progress_cb_was_called); + if ((error = git_remote_add_fetch(remote, "+refs/*:refs/*")) < 0) { + git_remote_free(remote); + return error; + } - git_remote_free(remote); - git_reference_free(head); - git_buf_free(&path); + *out = remote; + return 0; } void test_online_clone__clone_mirror(void) { - git_buf path = GIT_BUF_INIT; - git_remote *remote; + git_clone_options opts = GIT_CLONE_OPTIONS_INIT; git_reference *head; git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; bool fetch_progress_cb_was_called = false; - cl_git_pass(git_repository_init(&g_repo, "./foo.git", true)); - cl_git_pass(git_remote_create(&remote, g_repo, "origin", LIVE_REPO_URL)); - callbacks.transfer_progress = &fetch_progress; callbacks.payload = &fetch_progress_cb_was_called; - git_remote_set_callbacks(remote, &callbacks); - git_remote_clear_refspecs(remote); - cl_git_pass(git_remote_add_fetch(remote, "+refs/*:refs/*")); + opts.bare = true; + opts.remote_cb = remote_mirror_cb; + opts.remote_cb_payload = &callbacks; - cl_git_pass(git_clone_into(g_repo, remote, NULL, NULL, NULL)); + cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo.git", &opts)); cl_git_pass(git_reference_lookup(&head, g_repo, "HEAD")); cl_assert_equal_i(GIT_REF_SYMBOLIC, git_reference_type(head)); @@ -190,9 +174,7 @@ void test_online_clone__clone_mirror(void) cl_assert_equal_i(true, fetch_progress_cb_was_called); - git_remote_free(remote); git_reference_free(head); - git_buf_free(&path); git_repository_free(g_repo); g_repo = NULL; diff --git a/tests/pack/indexer.c b/tests/pack/indexer.c index 084f8e666..49a106d98 100644 --- a/tests/pack/indexer.c +++ b/tests/pack/indexer.c @@ -74,7 +74,7 @@ void test_pack_indexer__fix_thin(void) /* Store the missing base into your ODB so the indexer can fix the pack */ cl_git_pass(git_odb_write(&id, odb, base_obj, base_obj_len, GIT_OBJ_BLOB)); git_oid_fromstr(&should_id, "e68fe8129b546b101aee9510c5328e7f21ca1d18"); - cl_assert(!git_oid_cmp(&id, &should_id)); + cl_assert_equal_oid(&should_id, &id); cl_git_pass(git_indexer_new(&idx, ".", 0, odb, NULL, NULL)); cl_git_pass(git_indexer_append(idx, thin_pack, thin_pack_len, &stats)); @@ -86,7 +86,7 @@ void test_pack_indexer__fix_thin(void) cl_assert_equal_i(stats.local_objects, 1); git_oid_fromstr(&should_id, "11f0f69b334728fdd8bc86b80499f22f29d85b15"); - cl_assert(!git_oid_cmp(git_indexer_hash(idx), &should_id)); + cl_assert_equal_oid(&should_id, git_indexer_hash(idx)); git_indexer_free(idx); git_odb_free(odb); diff --git a/tests/pack/sharing.c b/tests/pack/sharing.c new file mode 100644 index 000000000..a67d65588 --- /dev/null +++ b/tests/pack/sharing.c @@ -0,0 +1,42 @@ +#include "clar_libgit2.h" +#include <git2.h> +#include "strmap.h" +#include "mwindow.h" +#include "pack.h" + +extern git_strmap *git__pack_cache; + +void test_pack_sharing__open_two_repos(void) +{ + git_repository *repo1, *repo2; + git_object *obj1, *obj2; + git_oid id; + git_strmap_iter pos; + void *data; + int error; + + cl_git_pass(git_repository_open(&repo1, cl_fixture("testrepo.git"))); + cl_git_pass(git_repository_open(&repo2, cl_fixture("testrepo.git"))); + + git_oid_fromstr(&id, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"); + + cl_git_pass(git_object_lookup(&obj1, repo1, &id, GIT_OBJ_ANY)); + cl_git_pass(git_object_lookup(&obj2, repo2, &id, GIT_OBJ_ANY)); + + pos = 0; + while ((error = git_strmap_next(&data, &pos, git__pack_cache)) == 0) { + struct git_pack_file *pack = (struct git_pack_file *) data; + + cl_assert_equal_i(2, pack->refcount.val); + } + + cl_assert_equal_i(3, git_strmap_num_entries(git__pack_cache)); + + git_object_free(obj1); + git_object_free(obj2); + git_repository_free(repo1); + git_repository_free(repo2); + + /* we don't want to keep the packs open after the repos go away */ + cl_assert_equal_i(0, git_strmap_num_entries(git__pack_cache)); +} diff --git a/tests/refs/create.c b/tests/refs/create.c index 50b8e84f8..8e4d8d70b 100644 --- a/tests/refs/create.c +++ b/tests/refs/create.c @@ -45,7 +45,7 @@ void test_refs_create__symbolic(void) cl_assert(git_reference_type(resolved_ref) == GIT_REF_OID); /* ...and that it points to the current master tip */ - cl_assert(git_oid_cmp(&id, git_reference_target(resolved_ref)) == 0); + cl_assert_equal_oid(&id, git_reference_target(resolved_ref)); git_reference_free(looked_up_ref); git_reference_free(resolved_ref); @@ -54,7 +54,7 @@ void test_refs_create__symbolic(void) cl_git_pass(git_reference_lookup(&looked_up_ref, repo2, new_head_tracker)); cl_git_pass(git_reference_resolve(&resolved_ref, looked_up_ref)); - cl_assert(git_oid_cmp(&id, git_reference_target(resolved_ref)) == 0); + cl_assert_equal_oid(&id, git_reference_target(resolved_ref)); git_repository_free(repo2); @@ -76,7 +76,7 @@ void test_refs_create__deep_symbolic(void) cl_git_pass(git_reference_symbolic_create(&new_reference, g_repo, new_head_tracker, current_head_target, 0, NULL, NULL)); cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, new_head_tracker)); cl_git_pass(git_reference_resolve(&resolved_ref, looked_up_ref)); - cl_assert(git_oid_cmp(&id, git_reference_target(resolved_ref)) == 0); + cl_assert_equal_oid(&id, git_reference_target(resolved_ref)); git_reference_free(new_reference); git_reference_free(looked_up_ref); @@ -104,14 +104,14 @@ void test_refs_create__oid(void) cl_assert_equal_s(looked_up_ref->name, new_head); /* ...and that it points to the current master tip */ - cl_assert(git_oid_cmp(&id, git_reference_target(looked_up_ref)) == 0); + cl_assert_equal_oid(&id, git_reference_target(looked_up_ref)); git_reference_free(looked_up_ref); /* Similar test with a fresh new repository */ cl_git_pass(git_repository_open(&repo2, "testrepo")); cl_git_pass(git_reference_lookup(&looked_up_ref, repo2, new_head)); - cl_assert(git_oid_cmp(&id, git_reference_target(looked_up_ref)) == 0); + cl_assert_equal_oid(&id, git_reference_target(looked_up_ref)); git_repository_free(repo2); diff --git a/tests/refs/createwithlog.c b/tests/refs/createwithlog.c index 026ff6d6a..ab13d7d15 100644 --- a/tests/refs/createwithlog.c +++ b/tests/refs/createwithlog.c @@ -42,7 +42,7 @@ void test_refs_createwithlog__creating_a_direct_reference_adds_a_reflog_entry(vo entry = git_reflog_entry_byindex(reflog, 0); cl_assert(git_oid_streq(&entry->oid_old, GIT_OID_HEX_ZERO) == 0); - cl_assert(git_oid_cmp(&id, &entry->oid_cur) == 0); + cl_assert_equal_oid(&id, &entry->oid_cur); cl_assert_equal_s(message, entry->msg); git_reflog_free(reflog); diff --git a/tests/refs/lookup.c b/tests/refs/lookup.c index 2e31cf0f6..d076e491f 100644 --- a/tests/refs/lookup.c +++ b/tests/refs/lookup.c @@ -44,7 +44,7 @@ void test_refs_lookup__oid(void) cl_git_pass(git_reference_name_to_id(&tag, g_repo, "refs/tags/point_to_blob")); cl_git_pass(git_oid_fromstr(&expected, "1385f264afb75a56a5bec74243be9b367ba4ca08")); - cl_assert(git_oid_cmp(&tag, &expected) == 0); + cl_assert_equal_oid(&expected, &tag); } void test_refs_lookup__namespace(void) diff --git a/tests/refs/overwrite.c b/tests/refs/overwrite.c index 78ce4ace7..c237d76f4 100644 --- a/tests/refs/overwrite.c +++ b/tests/refs/overwrite.c @@ -78,7 +78,7 @@ void test_refs_overwrite__object_id(void) /* Ensure it has been overwritten */ cl_git_pass(git_reference_lookup(&ref, g_repo, ref_name)); - cl_assert(!git_oid_cmp(&id, git_reference_target(ref))); + cl_assert_equal_oid(&id, git_reference_target(ref)); git_reference_free(ref); } @@ -130,7 +130,7 @@ void test_refs_overwrite__symbolic_with_object_id(void) /* Ensure it points to the right place */ cl_git_pass(git_reference_lookup(&ref, g_repo, ref_name)); cl_assert(git_reference_type(ref) & GIT_REF_OID); - cl_assert(!git_oid_cmp(git_reference_target(ref), &id)); + cl_assert_equal_oid(&id, git_reference_target(ref)); git_reference_free(ref); } diff --git a/tests/refs/peel.c b/tests/refs/peel.c index f2fb6e259..542694c47 100644 --- a/tests/refs/peel.c +++ b/tests/refs/peel.c @@ -33,7 +33,7 @@ static void assert_peel_generic( cl_git_pass(git_reference_peel(&peeled, ref, requested_type)); cl_git_pass(git_oid_fromstr(&expected_oid, expected_sha)); - cl_assert_equal_i(0, git_oid_cmp(&expected_oid, git_object_id(peeled))); + cl_assert_equal_oid(&expected_oid, git_object_id(peeled)); cl_assert_equal_i(expected_type, git_object_type(peeled)); diff --git a/tests/refs/read.c b/tests/refs/read.c index 52c307eb0..cb42a568b 100644 --- a/tests/refs/read.c +++ b/tests/refs/read.c @@ -83,7 +83,7 @@ void test_refs_read__symbolic(void) cl_assert(git_object_type(object) == GIT_OBJ_COMMIT); git_oid_fromstr(&id, current_master_tip); - cl_assert(git_oid_cmp(&id, git_object_id(object)) == 0); + cl_assert_equal_oid(&id, git_object_id(object)); git_object_free(object); @@ -111,7 +111,7 @@ void test_refs_read__nested_symbolic(void) cl_assert(git_object_type(object) == GIT_OBJ_COMMIT); git_oid_fromstr(&id, current_master_tip); - cl_assert(git_oid_cmp(&id, git_object_id(object)) == 0); + cl_assert_equal_oid(&id, git_object_id(object)); git_object_free(object); @@ -130,13 +130,13 @@ void test_refs_read__head_then_master(void) cl_git_pass(git_reference_lookup(&reference, g_repo, GIT_HEAD_FILE)); cl_git_pass(git_reference_resolve(&resolved_ref, reference)); - cl_git_pass(git_oid_cmp(git_reference_target(comp_base_ref), git_reference_target(resolved_ref))); + cl_assert_equal_oid(git_reference_target(comp_base_ref), git_reference_target(resolved_ref)); git_reference_free(reference); git_reference_free(resolved_ref); cl_git_pass(git_reference_lookup(&reference, g_repo, current_head_target)); cl_git_pass(git_reference_resolve(&resolved_ref, reference)); - cl_git_pass(git_oid_cmp(git_reference_target(comp_base_ref), git_reference_target(resolved_ref))); + cl_assert_equal_oid(git_reference_target(comp_base_ref), git_reference_target(resolved_ref)); git_reference_free(reference); git_reference_free(resolved_ref); @@ -152,7 +152,7 @@ void test_refs_read__master_then_head(void) cl_git_pass(git_reference_lookup(&reference, g_repo, GIT_HEAD_FILE)); cl_git_pass(git_reference_resolve(&resolved_ref, reference)); - cl_git_pass(git_oid_cmp(git_reference_target(master_ref), git_reference_target(resolved_ref))); + cl_assert_equal_oid(git_reference_target(master_ref), git_reference_target(resolved_ref)); git_reference_free(reference); git_reference_free(resolved_ref); @@ -201,7 +201,7 @@ void test_refs_read__chomped(void) cl_git_pass(git_reference_lookup(&test, g_repo, "refs/heads/test")); cl_git_pass(git_reference_lookup(&chomped, g_repo, "refs/heads/chomped")); - cl_git_pass(git_oid_cmp(git_reference_target(test), git_reference_target(chomped))); + cl_assert_equal_oid(git_reference_target(test), git_reference_target(chomped)); git_reference_free(test); git_reference_free(chomped); @@ -213,7 +213,7 @@ void test_refs_read__trailing(void) cl_git_pass(git_reference_lookup(&test, g_repo, "refs/heads/test")); cl_git_pass(git_reference_lookup(&trailing, g_repo, "refs/heads/trailing")); - cl_git_pass(git_oid_cmp(git_reference_target(test), git_reference_target(trailing))); + cl_assert_equal_oid(git_reference_target(test), git_reference_target(trailing)); git_reference_free(trailing); cl_git_pass(git_reference_lookup(&trailing, g_repo, "FETCH_HEAD")); diff --git a/tests/refs/rename.c b/tests/refs/rename.c index 88f0afd9c..c7901bd8b 100644 --- a/tests/refs/rename.c +++ b/tests/refs/rename.c @@ -220,7 +220,7 @@ void test_refs_rename__force_loose_packed(void) /* Check we actually renamed it */ cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_test_head_name)); cl_assert_equal_s(looked_up_ref->name, packed_test_head_name); - cl_assert(!git_oid_cmp(&oid, git_reference_target(looked_up_ref))); + cl_assert_equal_oid(&oid, git_reference_target(looked_up_ref)); git_reference_free(looked_up_ref); /* And that the previous one doesn't exist any longer */ @@ -245,7 +245,7 @@ void test_refs_rename__force_loose(void) /* Check we actually renamed it */ cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, "refs/heads/test")); cl_assert_equal_s(looked_up_ref->name, "refs/heads/test"); - cl_assert(!git_oid_cmp(&oid, git_reference_target(looked_up_ref))); + cl_assert_equal_oid(&oid, git_reference_target(looked_up_ref)); git_reference_free(looked_up_ref); /* And that the previous one doesn't exist any longer */ diff --git a/tests/refs/settargetwithlog.c b/tests/refs/settargetwithlog.c index 524ce771c..3a3378186 100644 --- a/tests/refs/settargetwithlog.c +++ b/tests/refs/settargetwithlog.c @@ -44,8 +44,8 @@ void test_refs_settargetwithlog__updating_a_direct_reference_adds_a_reflog_entry cl_git_pass(git_reflog_read(&reflog, g_repo, br2_name)); entry = git_reflog_entry_byindex(reflog, 0); - cl_assert(git_oid_cmp(¤t_id, &entry->oid_old) == 0); - cl_assert(git_oid_cmp(&target_id, &entry->oid_cur) == 0); + cl_assert_equal_oid(¤t_id, &entry->oid_old); + cl_assert_equal_oid(&target_id, &entry->oid_cur); cl_assert_equal_s(message, entry->msg); git_reflog_free(reflog); diff --git a/tests/refs/setter.c b/tests/refs/setter.c index 9a945db00..a5d073a56 100644 --- a/tests/refs/setter.c +++ b/tests/refs/setter.c @@ -41,7 +41,7 @@ void test_refs_setter__update_direct(void) cl_git_pass(git_reference_lookup(&test_ref, g_repo, ref_test_name)); cl_assert(git_reference_type(test_ref) == GIT_REF_OID); - cl_assert(git_oid_cmp(&id, git_reference_target(test_ref)) == 0); + cl_assert_equal_oid(&id, git_reference_target(test_ref)); git_reference_free(test_ref); } diff --git a/tests/refs/unicode.c b/tests/refs/unicode.c index 471b0b8d3..9c7527cd7 100644 --- a/tests/refs/unicode.c +++ b/tests/refs/unicode.c @@ -32,8 +32,7 @@ void test_refs_unicode__create_and_lookup(void) cl_git_pass(git_repository_open(&repo2, "testrepo.git")); cl_git_pass(git_reference_lookup(&ref2, repo2, REFNAME)); - cl_assert_equal_i( - 0, git_oid_cmp(git_reference_target(ref1), git_reference_target(ref2))); + cl_assert_equal_oid(git_reference_target(ref1), git_reference_target(ref2)); cl_assert_equal_s(REFNAME, git_reference_name(ref2)); git_reference_free(ref2); @@ -43,8 +42,7 @@ void test_refs_unicode__create_and_lookup(void) #define REFNAME_DECOMPOSED "refs/heads/" "A" "\314\212" "ngstro" "\314\210" "m" cl_git_pass(git_reference_lookup(&ref2, repo2, REFNAME_DECOMPOSED)); - cl_assert_equal_i( - 0, git_oid_cmp(git_reference_target(ref1), git_reference_target(ref2))); + cl_assert_equal_oid(git_reference_target(ref1), git_reference_target(ref2)); cl_assert_equal_s(REFNAME, git_reference_name(ref2)); git_reference_free(ref2); #endif diff --git a/tests/repo/hashfile.c b/tests/repo/hashfile.c index 4cc9f18b4..ae8e122f6 100644 --- a/tests/repo/hashfile.c +++ b/tests/repo/hashfile.c @@ -22,14 +22,14 @@ void test_repo_hashfile__simple(void) /* hash with repo relative path */ cl_git_pass(git_odb_hashfile(&a, "status/current_file", GIT_OBJ_BLOB)); cl_git_pass(git_repository_hashfile(&b, _repo, "current_file", GIT_OBJ_BLOB, NULL)); - cl_assert(git_oid_equal(&a, &b)); + cl_assert_equal_oid(&a, &b); cl_git_pass(git_buf_joinpath(&full, git_repository_workdir(_repo), "current_file")); /* hash with full path */ cl_git_pass(git_odb_hashfile(&a, full.ptr, GIT_OBJ_BLOB)); cl_git_pass(git_repository_hashfile(&b, _repo, full.ptr, GIT_OBJ_BLOB, NULL)); - cl_assert(git_oid_equal(&a, &b)); + cl_assert_equal_oid(&a, &b); /* hash with invalid type */ cl_git_fail(git_odb_hashfile(&a, full.ptr, GIT_OBJ_ANY)); @@ -58,12 +58,12 @@ void test_repo_hashfile__filtered(void) /* equal hashes because filter is binary */ cl_git_pass(git_odb_hashfile(&a, "status/testfile.bin", GIT_OBJ_BLOB)); cl_git_pass(git_repository_hashfile(&b, _repo, "testfile.bin", GIT_OBJ_BLOB, NULL)); - cl_assert(git_oid_equal(&a, &b)); + cl_assert_equal_oid(&a, &b); /* equal hashes when 'as_file' points to binary filtering */ cl_git_pass(git_odb_hashfile(&a, "status/testfile.txt", GIT_OBJ_BLOB)); cl_git_pass(git_repository_hashfile(&b, _repo, "testfile.txt", GIT_OBJ_BLOB, "foo.bin")); - cl_assert(git_oid_equal(&a, &b)); + cl_assert_equal_oid(&a, &b); /* not equal hashes when 'as_file' points to text filtering */ cl_git_pass(git_odb_hashfile(&a, "status/testfile.bin", GIT_OBJ_BLOB)); @@ -73,11 +73,11 @@ void test_repo_hashfile__filtered(void) /* equal hashes when 'as_file' is empty and turns off filtering */ cl_git_pass(git_odb_hashfile(&a, "status/testfile.txt", GIT_OBJ_BLOB)); cl_git_pass(git_repository_hashfile(&b, _repo, "testfile.txt", GIT_OBJ_BLOB, "")); - cl_assert(git_oid_equal(&a, &b)); + cl_assert_equal_oid(&a, &b); cl_git_pass(git_odb_hashfile(&a, "status/testfile.bin", GIT_OBJ_BLOB)); cl_git_pass(git_repository_hashfile(&b, _repo, "testfile.bin", GIT_OBJ_BLOB, "")); - cl_assert(git_oid_equal(&a, &b)); + cl_assert_equal_oid(&a, &b); /* some hash type failures */ cl_git_fail(git_odb_hashfile(&a, "status/testfile.txt", 0)); diff --git a/tests/repo/head.c b/tests/repo/head.c index 79892a3ea..d678e150e 100644 --- a/tests/repo/head.c +++ b/tests/repo/head.c @@ -229,13 +229,13 @@ static void test_reflog(git_repository *repo, size_t idx, if (old_spec) { git_object *obj; cl_git_pass(git_revparse_single(&obj, repo, old_spec)); - cl_assert_equal_i(0, git_oid_cmp(git_object_id(obj), git_reflog_entry_id_old(entry))); + cl_assert_equal_oid(git_object_id(obj), git_reflog_entry_id_old(entry)); git_object_free(obj); } if (new_spec) { git_object *obj; cl_git_pass(git_revparse_single(&obj, repo, new_spec)); - cl_assert_equal_i(0, git_oid_cmp(git_object_id(obj), git_reflog_entry_id_new(entry))); + cl_assert_equal_oid(git_object_id(obj), git_reflog_entry_id_new(entry)); git_object_free(obj); } diff --git a/tests/revwalk/hidecb.c b/tests/revwalk/hidecb.c index 26ff183fa..14cf39afd 100644 --- a/tests/revwalk/hidecb.c +++ b/tests/revwalk/hidecb.c @@ -69,21 +69,15 @@ static int hide_commit_cb(const git_oid *commit_id, void *data) GIT_UNUSED(commit_id); GIT_UNUSED(data); - if (0 == git_oid_cmp(commit_id, &commit_ids[5])) - return 1; - else - return 0; - + return (git_oid_cmp(commit_id, &commit_ids[5]) == 0); } /* In payload data, pointer to a commit id is passed */ static int hide_commit_use_payload_cb(const git_oid *commit_id, void *data) { git_oid *hide_commit_id = data; - if (git_oid_cmp(commit_id, hide_commit_id) == 0) - return 1; - else - return 0; + + return (git_oid_cmp(commit_id, hide_commit_id) == 0); } void test_revwalk_hidecb__hide_all_cb(void) @@ -170,7 +164,7 @@ void test_revwalk_hidecb__hide_some_commits(void) i = 0; while ((error = git_revwalk_next(&id, walk)) == 0) { - cl_assert_equal_i(git_oid_cmp(&id, &commit_ids[i]), 0); + cl_assert_equal_oid(&commit_ids[i], &id); i++; } @@ -194,7 +188,7 @@ void test_revwalk_hidecb__test_payload(void) i = 0; while ((error = git_revwalk_next(&id, walk)) == 0) { - cl_assert_equal_i(git_oid_cmp(&id, &commit_ids[i]), 0); + cl_assert_equal_oid(&commit_ids[i], &id); i++; } diff --git a/tests/revwalk/mergebase.c b/tests/revwalk/mergebase.c index 97663502c..2c7184fc7 100644 --- a/tests/revwalk/mergebase.c +++ b/tests/revwalk/mergebase.c @@ -30,7 +30,7 @@ void test_revwalk_mergebase__single1(void) cl_git_pass(git_oid_fromstr(&expected, "5b5b025afb0b4c913b4c338a42934a3863bf3644")); cl_git_pass(git_merge_base(&result, _repo, &one, &two)); - cl_assert(git_oid_cmp(&result, &expected) == 0); + cl_assert_equal_oid(&expected, &result); cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo, &one, &two)); cl_assert_equal_sz(ahead, 2); @@ -51,7 +51,7 @@ void test_revwalk_mergebase__single2(void) cl_git_pass(git_oid_fromstr(&expected, "c47800c7266a2be04c571c04d5a6614691ea99bd")); cl_git_pass(git_merge_base(&result, _repo, &one, &two)); - cl_assert(git_oid_cmp(&result, &expected) == 0); + cl_assert_equal_oid(&expected, &result); cl_git_pass(git_graph_ahead_behind( &ahead, &behind, _repo, &one, &two)); cl_assert_equal_sz(ahead, 4); @@ -72,10 +72,10 @@ void test_revwalk_mergebase__merged_branch(void) cl_git_pass(git_oid_fromstr(&expected, "9fd738e8f7967c078dceed8190330fc8648ee56a")); cl_git_pass(git_merge_base(&result, _repo, &one, &two)); - cl_assert(git_oid_cmp(&result, &expected) == 0); + cl_assert_equal_oid(&expected, &result); cl_git_pass(git_merge_base(&result, _repo, &two, &one)); - cl_assert(git_oid_cmp(&result, &expected) == 0); + cl_assert_equal_oid(&expected, &result); cl_git_pass(git_graph_ahead_behind(&ahead, &behind, _repo, &one, &two)); cl_assert_equal_sz(ahead, 0); @@ -132,7 +132,7 @@ void test_revwalk_mergebase__prefer_youngest_merge_base(void) cl_git_pass(git_oid_fromstr(&expected, "c47800c7266a2be04c571c04d5a6614691ea99bd")); cl_git_pass(git_merge_base(&result, _repo, &one, &two)); - cl_assert(git_oid_cmp(&result, &expected) == 0); + cl_assert_equal_oid(&expected, &result); } void test_revwalk_mergebase__no_off_by_one_missing(void) @@ -177,7 +177,7 @@ static void assert_mergebase_many(const char *expected_sha, int count, ...) cl_git_pass(git_merge_base_many(&oid, _repo, count, oids)); cl_git_pass(git_oid_fromstr(&expected, expected_sha)); - cl_assert(git_oid_cmp(&expected, &oid) == 0); + cl_assert_equal_oid(&expected, &oid); } git__free(oids); @@ -241,7 +241,7 @@ static void assert_mergebase_octopus(const char *expected_sha, int count, ...) cl_git_pass(git_merge_base_octopus(&oid, _repo, count, oids)); cl_git_pass(git_oid_fromstr(&expected, expected_sha)); - cl_assert(git_oid_cmp(&expected, &oid) == 0); + cl_assert_equal_oid(&expected, &oid); } git__free(oids); diff --git a/tests/revwalk/simplify.c b/tests/revwalk/simplify.c index 81c19d366..f65ce6c59 100644 --- a/tests/revwalk/simplify.c +++ b/tests/revwalk/simplify.c @@ -20,8 +20,8 @@ static const char *commit_head = "a4a7dce85cf63874e984719f4fdd239f5145052f"; static const char *expected_str[] = { "a4a7dce85cf63874e984719f4fdd239f5145052f", /* 0 */ "c47800c7266a2be04c571c04d5a6614691ea99bd", /* 3 */ - "8496071c1b46c854b31185ea97743be6a8774479", /* 4 */ - "5b5b025afb0b4c913b4c338a42934a3863bf3644", /* 5 */ + "5b5b025afb0b4c913b4c338a42934a3863bf3644", /* 4 */ + "8496071c1b46c854b31185ea97743be6a8774479", /* 5 */ }; void test_revwalk_simplify__first_parent(void) @@ -44,7 +44,7 @@ void test_revwalk_simplify__first_parent(void) i = 0; while ((error = git_revwalk_next(&id, walk)) == 0) { - git_oid_cmp(&id, &expected[i]); + cl_assert_equal_oid(&expected[i], &id); i++; } diff --git a/tests/stash/drop.c b/tests/stash/drop.c index 63ff0377c..89a0ade72 100644 --- a/tests/stash/drop.c +++ b/tests/stash/drop.c @@ -115,7 +115,7 @@ void test_stash_drop__dropping_an_entry_rewrites_reflog_history(void) cl_git_pass(git_reflog_read(&reflog, repo, GIT_REFS_STASH_FILE)); entry = git_reflog_entry_byindex(reflog, 0); - cl_assert_equal_i(0, git_oid_cmp(&oid, git_reflog_entry_id_old(entry))); + cl_assert_equal_oid(&oid, git_reflog_entry_id_old(entry)); cl_assert_equal_sz(count - 1, git_reflog_entrycount(reflog)); git_reflog_free(reflog); @@ -147,7 +147,7 @@ void retrieve_top_stash_id(git_oid *out) cl_git_pass(git_revparse_single(&top_stash, repo, "stash@{0}")); cl_git_pass(git_reference_name_to_id(out, repo, GIT_REFS_STASH_FILE)); - cl_assert_equal_i(true, git_oid_cmp(out, git_object_id(top_stash)) == 0); + cl_assert_equal_oid(out, git_object_id(top_stash)); git_object_free(top_stash); } @@ -162,13 +162,13 @@ void test_stash_drop__dropping_the_top_stash_updates_the_stash_reference(void) retrieve_top_stash_id(&oid); cl_git_pass(git_revparse_single(&next_top_stash, repo, "stash@{1}")); - cl_assert(git_oid_cmp(&oid, git_object_id(next_top_stash)) != 0); + cl_assert(git_oid_cmp(&oid, git_object_id(next_top_stash))); cl_git_pass(git_stash_drop(repo, 0)); retrieve_top_stash_id(&oid); - cl_git_pass(git_oid_cmp(&oid, git_object_id(next_top_stash))); + cl_assert_equal_oid(&oid, git_object_id(next_top_stash)); git_object_free(next_top_stash); } diff --git a/tests/status/single.c b/tests/status/single.c index 292c9120a..6efaab294 100644 --- a/tests/status/single.c +++ b/tests/status/single.c @@ -22,7 +22,7 @@ void test_status_single__hash_single_file(void) cl_set_cleanup(&cleanup__remove_file, (void *)file_name); cl_git_pass(git_odb_hashfile(&actual_id, file_name, GIT_OBJ_BLOB)); - cl_assert(git_oid_cmp(&expected_id, &actual_id) == 0); + cl_assert_equal_oid(&expected_id, &actual_id); } /* test retrieving OID from an empty file apart from the ODB */ @@ -40,6 +40,6 @@ void test_status_single__hash_single_empty_file(void) cl_set_cleanup(&cleanup__remove_file, (void *)file_name); cl_git_pass(git_odb_hashfile(&actual_id, file_name, GIT_OBJ_BLOB)); - cl_assert(git_oid_cmp(&expected_id, &actual_id) == 0); + cl_assert_equal_oid(&expected_id, &actual_id); } |