From 32269b15e2fc2e5477b8ccfb724cd087c6a41ce7 Mon Sep 17 00:00:00 2001 From: Tyler Church Date: Wed, 18 May 2016 09:33:17 -0700 Subject: [PATCH 001/366] Add retries to win32 p_unlink and p_open. --- src/win32/posix_w32.c | 46 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c index fea634b00..e89b065e6 100644 --- a/src/win32/posix_w32.c +++ b/src/win32/posix_w32.c @@ -93,17 +93,31 @@ int p_unlink(const char *path) { git_win32_path buf; int error; + int unlink_tries; if (git_win32_path_from_utf8(buf, path) < 0) return -1; - error = _wunlink(buf); - - /* If the file could not be deleted because it was - * read-only, clear the bit and try again */ - if (error == -1 && errno == EACCES) { - _wchmod(buf, 0666); + /* wait up to 50ms if file is locked by another thread or process */ + unlink_tries = 0; + while (unlink_tries < 10) { error = _wunlink(buf); + + /* If the file could not be deleted because it was + * read-only, clear the bit and try again */ + if (error == -1 && errno == EACCES) { + _wchmod(buf, 0666); + error = _wunlink(buf); + + if (error == -1 && errno == EACCES) { + Sleep(5); + unlink_tries++; + } else { + break; + } + } else { + break; + } } return error; @@ -284,6 +298,8 @@ int p_open(const char *path, int flags, ...) { git_win32_path buf; mode_t mode = 0; + int open_tries; + int handle; if (git_win32_path_from_utf8(buf, path) < 0) return -1; @@ -296,7 +312,23 @@ int p_open(const char *path, int flags, ...) va_end(arg_list); } - return _wopen(buf, flags | STANDARD_OPEN_FLAGS, mode & WIN32_MODE_MASK); + /* wait up to 50ms if file is locked by another thread or process */ + open_tries = 0; + while (open_tries < 10) { + handle = _wopen(buf, flags | STANDARD_OPEN_FLAGS, mode & WIN32_MODE_MASK); + if (handle != -1) { + break; + } + + if (errno == EACCES) { + Sleep(5); + open_tries++; + } else { + break; + } + } + + return handle; } int p_creat(const char *path, mode_t mode) From 452bf57cbe665768810f2597aba50b9afc9509a7 Mon Sep 17 00:00:00 2001 From: Richard Ipsum Date: Sat, 27 Aug 2016 13:42:53 +0100 Subject: [PATCH 002/366] Make symbolic ref target validation optional Introduce GIT_OPT_ENABLE_SYMBOLIC_REF_TARGET_VALIDATION option. Setting this option to 0 allows validation of a symbolic ref's target to be bypassed. This option is enabled by default. This mechanism is added primarily to address a discrepancy between git behaviour and libgit2 behaviour, whereby the former allows the symbolic ref target to carry an arbitrary string and the latter does not, so: $ git symbolic-ref refs/heads/foo bar $ cat .git/refs/heads/foo ref: bar where as attempting the same via libgit2 raises an error: The given reference name 'bar' is not valid this mechanism also allows those that might want to make use of git's more lenient treatment of symbolic ref targets to do so. --- include/git2/common.h | 13 +++++++++++++ src/refs.c | 45 +++++++++++++++++++++++++++++++++++++++---- src/refs.h | 3 +++ src/settings.c | 5 +++++ 4 files changed, 62 insertions(+), 4 deletions(-) diff --git a/include/git2/common.h b/include/git2/common.h index 18abe46b3..02d263048 100644 --- a/include/git2/common.h +++ b/include/git2/common.h @@ -157,6 +157,7 @@ typedef enum { GIT_OPT_SET_SSL_CERT_LOCATIONS, GIT_OPT_SET_USER_AGENT, GIT_OPT_ENABLE_STRICT_OBJECT_CREATION, + GIT_OPT_ENABLE_SYMBOLIC_REF_TARGET_VALIDATION, GIT_OPT_SET_SSL_CIPHERS, GIT_OPT_GET_USER_AGENT, } git_libgit2_opt_t; @@ -270,6 +271,18 @@ typedef enum { * > example, when this is enabled, the parent(s) and tree inputs * > will be validated when creating a new commit. This defaults * > to disabled. + * + * * opts(GIT_OPT_ENABLE_SYMBOLIC_REF_TARGET_VALIDATION, int enabled) + * + * > Validate the target of a symbolic ref when creating it. + * > For example, 'foobar' is not a valid ref, + * > therefore 'foobar' is not a valid target + * > for a symbolic ref by default, + * > where as 'refs/heads/foobar' is. + * > Disabling this bypasses validation so that an arbitrary + * > strings such as 'foobar' can be used for a symbolic ref target. + * > This defaults to enabled. + * * * opts(GIT_OPT_SET_SSL_CIPHERS, const char *ciphers) * * > Set the SSL ciphers use for HTTPS connections. diff --git a/src/refs.c b/src/refs.c index bff443ac9..c77653da8 100644 --- a/src/refs.c +++ b/src/refs.c @@ -24,6 +24,8 @@ #include #include +bool git_reference__enable_symbolic_ref_target_validation = true; + GIT__USE_STRMAP #define DEFAULT_NESTING_LEVEL 5 @@ -175,10 +177,11 @@ int git_reference_name_to_id( return 0; } -static int reference_normalize_for_repo( +static int reference__normalize_for_repo( git_refname_t out, git_repository *repo, - const char *name) + const char *name, + bool validate) { int precompose; unsigned int flags = GIT_REF_FORMAT_ALLOW_ONELEVEL; @@ -187,9 +190,29 @@ static int reference_normalize_for_repo( precompose) flags |= GIT_REF_FORMAT__PRECOMPOSE_UNICODE; + if (!validate) { + flags |= GIT_REF_VALIDATION_DISABLE; + } + return git_reference_normalize_name(out, GIT_REFNAME_MAX, name, flags); } +static int reference_normalize_for_repo( + git_refname_t out, + git_repository *repo, + const char *name) +{ + return reference__normalize_for_repo(out, repo, name, true); +} + +static int reference_normalize_for_repo_without_validation( + git_refname_t out, + git_repository *repo, + const char *name) +{ + return reference__normalize_for_repo(out, repo, name, false); +} + int git_reference_lookup_resolved( git_reference **ref_out, git_repository *repo, @@ -404,7 +427,13 @@ static int reference__create( } else { git_refname_t normalized_target; - if ((error = reference_normalize_for_repo(normalized_target, repo, symbolic)) < 0) + if (git_reference__enable_symbolic_ref_target_validation) { + error = reference_normalize_for_repo(normalized_target, repo, symbolic); + } else { + error = reference_normalize_for_repo_without_validation(normalized_target, repo, symbolic); + } + + if (error < 0) return error; ref = git_reference__alloc_symbolic(normalized, normalized_target); @@ -876,6 +905,7 @@ int git_reference__normalize_name( int segment_len, segments_count = 0, error = GIT_EINVALIDSPEC; unsigned int process_flags; bool normalize = (buf != NULL); + bool validate = (flags & GIT_REF_VALIDATION_DISABLE) == 0; #ifdef GIT_USE_ICONV git_path_iconv_t ic = GIT_PATH_ICONV_INIT; @@ -886,7 +916,7 @@ int git_reference__normalize_name( process_flags = flags; current = (char *)name; - if (*current == '/') + if (validate && *current == '/') goto cleanup; if (normalize) @@ -902,6 +932,13 @@ int git_reference__normalize_name( } #endif + if (!validate) { + git_buf_sets(buf, current); + + error = git_buf_oom(buf) ? -1 : 0; + goto cleanup; + } + while (true) { segment_len = ensure_segment_validity(current); if (segment_len < 0) { diff --git a/src/refs.h b/src/refs.h index fda9532de..c4786ddb4 100644 --- a/src/refs.h +++ b/src/refs.h @@ -15,6 +15,8 @@ #include "buffer.h" #include "oid.h" +extern bool git_reference__enable_symbolic_ref_target_validation; + #define GIT_REFS_DIR "refs/" #define GIT_REFS_HEADS_DIR GIT_REFS_DIR "heads/" #define GIT_REFS_TAGS_DIR GIT_REFS_DIR "tags/" @@ -53,6 +55,7 @@ #define GIT_REFS_STASH_FILE GIT_REFS_DIR GIT_STASH_FILE #define GIT_REF_FORMAT__PRECOMPOSE_UNICODE (1u << 16) +#define GIT_REF_VALIDATION_DISABLE (1u << 15) #define GIT_REFNAME_MAX 1024 diff --git a/src/settings.c b/src/settings.c index cb2317f74..1fcdce2ed 100644 --- a/src/settings.c +++ b/src/settings.c @@ -15,6 +15,7 @@ #include "cache.h" #include "global.h" #include "object.h" +#include "refs.h" void git_libgit2_version(int *major, int *minor, int *rev) { @@ -191,6 +192,10 @@ int git_libgit2_opts(int key, ...) git_object__strict_input_validation = (va_arg(ap, int) != 0); break; + case GIT_OPT_ENABLE_SYMBOLIC_REF_TARGET_VALIDATION: + git_reference__enable_symbolic_ref_target_validation = (va_arg(ap, int) != 0); + break; + case GIT_OPT_SET_SSL_CIPHERS: #ifdef GIT_OPENSSL { From 567fd782d92e0e55724e93931faf28005d71904e Mon Sep 17 00:00:00 2001 From: Josh Leeb-du Toit Date: Mon, 26 Sep 2016 19:32:15 +1000 Subject: [PATCH 003/366] Remove `clone_checkout_strategy` in submodule update opts Remove `clone_checkout_strategy` in `git_submodule_update_options` as per issue #3784. --- CHANGELOG.md | 4 ++++ include/git2/submodule.h | 13 ++----------- src/submodule.c | 2 +- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dae86de4a..1c5644b70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -61,6 +61,10 @@ v0.24 + 1 * `git_blob_create_fromchunks()` has been removed in favour of `git_blob_create_fromstream()`. +* `clone_checkout_strategy` has been removed from + `git_submodule_update_option` as it is no longer necessary after + removing the `GIT_CHECKOUT_SAFE_CREATE` flag in favour of the 'GIT_CHECKOUT_SAFE' flag. + ### Breaking API changes * `git_packbuilder_object_count` and `git_packbuilder_written` now diff --git a/include/git2/submodule.h b/include/git2/submodule.h index 540ecf5c7..ab5d7b6f5 100644 --- a/include/git2/submodule.h +++ b/include/git2/submodule.h @@ -134,9 +134,7 @@ typedef struct git_submodule_update_options { * checkout, set the `checkout_strategy` to * `GIT_CHECKOUT_NONE`. Generally you will want the use * GIT_CHECKOUT_SAFE to update files in the working - * directory. Use the `clone_checkout_strategy` field - * to set the checkout strategy that will be used in - * the case where update needs to clone the repository. + * directory. */ git_checkout_options checkout_opts; @@ -148,13 +146,6 @@ typedef struct git_submodule_update_options { */ git_fetch_options fetch_opts; - /** - * The checkout strategy to use when the sub repository needs to - * be cloned. Use GIT_CHECKOUT_SAFE to create all files - * in the working directory for the newly cloned repository. - */ - unsigned int clone_checkout_strategy; - /** * Allow fetching from the submodule's default remote if the target * commit isn't found. Enabled by default. @@ -166,7 +157,7 @@ typedef struct git_submodule_update_options { #define GIT_SUBMODULE_UPDATE_OPTIONS_INIT \ { GIT_SUBMODULE_UPDATE_OPTIONS_VERSION, \ { GIT_CHECKOUT_OPTIONS_VERSION, GIT_CHECKOUT_SAFE }, \ - GIT_FETCH_OPTIONS_INIT, GIT_CHECKOUT_SAFE, 1 } + GIT_FETCH_OPTIONS_INIT, GIT_CHECKOUT_SAFE } /** * Initializes a `git_submodule_update_options` with default values. diff --git a/src/submodule.c b/src/submodule.c index 86ad53be0..0175ac5d7 100644 --- a/src/submodule.c +++ b/src/submodule.c @@ -1160,7 +1160,7 @@ int git_submodule_update(git_submodule *sm, int init, git_submodule_update_optio * will checkout the specific commit manually. */ clone_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_NONE; - update_options.checkout_opts.checkout_strategy = update_options.clone_checkout_strategy; + update_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; if ((error = git_clone(&sub_repo, submodule_url, sm->path, &clone_options)) < 0 || (error = git_repository_set_head_detached(sub_repo, git_submodule_index_id(sm))) < 0 || From dc976e72e9f73a3e74afd8d8abbe8483175ca49e Mon Sep 17 00:00:00 2001 From: Josh Leeb-du Toit Date: Wed, 28 Sep 2016 14:44:28 +1000 Subject: [PATCH 004/366] Reword CHANGELOG entry as per code review --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c5644b70..b65e498f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -62,8 +62,8 @@ v0.24 + 1 `git_blob_create_fromstream()`. * `clone_checkout_strategy` has been removed from - `git_submodule_update_option` as it is no longer necessary after - removing the `GIT_CHECKOUT_SAFE_CREATE` flag in favour of the 'GIT_CHECKOUT_SAFE' flag. + `git_submodule_update_option`. The checkout strategy used to clone will + be the same strategy specified in `checkout_opts`. ### Breaking API changes From 3e22bb71f2ca6f632059e53414dd19fb0349c482 Mon Sep 17 00:00:00 2001 From: Josh Leeb-du Toit Date: Wed, 28 Sep 2016 14:45:18 +1000 Subject: [PATCH 005/366] Update submodule update opts init as per code review Update the `GIT_SUBMODULE_UPDATE_OPTIONS_INIT` definition with the correct values after removing `clone_checkout_strategy` in `git_submodule_update_options`. --- include/git2/submodule.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/git2/submodule.h b/include/git2/submodule.h index ab5d7b6f5..b2b3039fe 100644 --- a/include/git2/submodule.h +++ b/include/git2/submodule.h @@ -157,7 +157,7 @@ typedef struct git_submodule_update_options { #define GIT_SUBMODULE_UPDATE_OPTIONS_INIT \ { GIT_SUBMODULE_UPDATE_OPTIONS_VERSION, \ { GIT_CHECKOUT_OPTIONS_VERSION, GIT_CHECKOUT_SAFE }, \ - GIT_FETCH_OPTIONS_INIT, GIT_CHECKOUT_SAFE } + GIT_FETCH_OPTIONS_INIT, 1 } /** * Initializes a `git_submodule_update_options` with default values. From ba3a8304ab53e9711cce5aec4ffa5668300034b1 Mon Sep 17 00:00:00 2001 From: Josh Leeb-du Toit Date: Mon, 10 Oct 2016 09:38:21 +1100 Subject: [PATCH 006/366] Remove set of submodule update `checkout_strategy` Remove overriding the `checkout_strategy` for `update_options` when performing an update on a submodule. Users should be specifying the correct checkout strategy in `update_options.checkout_opts.checkout_strategy`. --- src/submodule.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/submodule.c b/src/submodule.c index 0175ac5d7..ac6998603 100644 --- a/src/submodule.c +++ b/src/submodule.c @@ -1160,7 +1160,6 @@ int git_submodule_update(git_submodule *sm, int init, git_submodule_update_optio * will checkout the specific commit manually. */ clone_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_NONE; - update_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; if ((error = git_clone(&sub_repo, submodule_url, sm->path, &clone_options)) < 0 || (error = git_repository_set_head_detached(sub_repo, git_submodule_index_id(sm))) < 0 || From 6d354747acf9f76200355b79907c1f370d29e8d6 Mon Sep 17 00:00:00 2001 From: Arthur Schreiber Date: Tue, 18 Oct 2016 08:20:41 +0200 Subject: [PATCH 007/366] Perf: Don't perform merge operations for trivial merges. When one side of a merge is treesame to the ancestor, we can take the other side and skip all the expensive merge operations. This optimization can only be performed when the generation of REUC extension data is skipped. --- src/merge.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/merge.c b/src/merge.c index 6934aa731..2a8fc7fa6 100644 --- a/src/merge.c +++ b/src/merge.c @@ -2018,6 +2018,26 @@ int git_merge_trees( git_iterator_options iter_opts = GIT_ITERATOR_OPTIONS_INIT; int error; + assert(out && repo); + + /* if one side is treesame to the ancestor, take the other side */ + if (ancestor_tree && merge_opts && (merge_opts->flags & GIT_MERGE_SKIP_REUC)) { + const git_tree *result = NULL; + const git_oid *ancestor_tree_id = git_tree_id(ancestor_tree); + + if (our_tree && !git_oid_cmp(ancestor_tree_id, git_tree_id(our_tree))) + result = their_tree; + else if (their_tree && !git_oid_cmp(ancestor_tree_id, git_tree_id(their_tree))) + result = our_tree; + + if (result) { + if ((error = git_index_new(out)) == 0) + error = git_index_read_tree(*out, result); + + return error; + } + } + iter_opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE; if ((error = git_iterator_for_tree( From 236a690ce4cbcbaf243dda8853832de8485bac3f Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Sun, 20 Nov 2016 22:46:01 -0800 Subject: [PATCH 008/366] Allow Windows with WinHTTP to use external http-parser --- CMakeLists.txt | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f26f46879..8cc43c6ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -235,10 +235,21 @@ IF (WIN32 AND EMBED_SSH_PATH) ADD_DEFINITIONS(-DGIT_SSH) ENDIF() -IF (WIN32 AND WINHTTP) - ADD_DEFINITIONS(-DGIT_WINHTTP) + +FIND_PACKAGE(HTTP_Parser) +IF (HTTP_PARSER_FOUND AND HTTP_PARSER_VERSION_MAJOR EQUAL 2) + INCLUDE_DIRECTORIES(${HTTP_PARSER_INCLUDE_DIRS}) + LINK_LIBRARIES(${HTTP_PARSER_LIBRARIES}) + LIST(APPEND LIBGIT2_PC_LIBS "-lhttp_parser") +ELSE() + MESSAGE(STATUS "http-parser was not found or is too old; using bundled 3rd-party sources.") INCLUDE_DIRECTORIES(deps/http-parser) FILE(GLOB SRC_HTTP deps/http-parser/*.c deps/http-parser/*.h) +ENDIF() + + +IF (WIN32 AND WINHTTP) + ADD_DEFINITIONS(-DGIT_WINHTTP) # Since MinGW does not come with headers or an import library for winhttp, # we have to include a private header and generate our own import library @@ -291,17 +302,6 @@ ELSE () LINK_LIBRARIES(${CURL_LIBRARIES}) LIST(APPEND LIBGIT2_PC_LIBS ${CURL_LDFLAGS}) ENDIF() - - FIND_PACKAGE(HTTP_Parser) - IF (HTTP_PARSER_FOUND AND HTTP_PARSER_VERSION_MAJOR EQUAL 2) - INCLUDE_DIRECTORIES(${HTTP_PARSER_INCLUDE_DIRS}) - LINK_LIBRARIES(${HTTP_PARSER_LIBRARIES}) - LIST(APPEND LIBGIT2_PC_LIBS "-lhttp_parser") - ELSE() - MESSAGE(STATUS "http-parser was not found or is too old; using bundled 3rd-party sources.") - INCLUDE_DIRECTORIES(deps/http-parser) - FILE(GLOB SRC_HTTP deps/http-parser/*.c deps/http-parser/*.h) - ENDIF() ENDIF() # Specify sha1 implementation From 87aaefe20b2e2fad8f0b8b236d1c23ce9ec5340f Mon Sep 17 00:00:00 2001 From: Michael Tesch Date: Tue, 9 Aug 2016 12:23:19 -0400 Subject: [PATCH 009/366] write_tree: use shared buffer for writing trees The function to write trees allocates a new buffer for each tree. This causes problems with performance when performing a lot of actions involving writing trees, e.g. when doing many merges. Fix the issue by instead handing in a shared buffer, which is then re-used across the calls without having to re-allocate between calls. --- include/git2/tree.h | 13 +++++++++++++ src/tree.c | 45 ++++++++++++++++++++++++++++++--------------- 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/include/git2/tree.h b/include/git2/tree.h index 2e4735c4b..a38215f9f 100644 --- a/include/git2/tree.h +++ b/include/git2/tree.h @@ -375,6 +375,19 @@ GIT_EXTERN(void) git_treebuilder_filter( GIT_EXTERN(int) git_treebuilder_write( git_oid *id, git_treebuilder *bld); +/** + * Write the contents of the tree builder as a tree object + * using a shared git_buf. + * + * @see git_treebuilder_write + * + * @param id Pointer to store the OID of the newly written tree + * @param bld Tree builder to write + * @param tree Shared buffer for writing the tree. Will be grown as necessary. + * @return 0 or an error code + */ +GIT_EXTERN(int) git_treebuilder_write_with_buffer( + git_oid *oid, git_treebuilder *bld, git_buf *tree); /** Callback for the tree traversal method */ typedef int (*git_treewalk_cb)( diff --git a/src/tree.c b/src/tree.c index 5db2446bf..0a155a9e4 100644 --- a/src/tree.c +++ b/src/tree.c @@ -515,7 +515,8 @@ static int write_tree( git_repository *repo, git_index *index, const char *dirname, - size_t start) + size_t start, + git_buf *shared_buf) { git_treebuilder *bld = NULL; size_t i, entries = git_index_entrycount(index); @@ -568,7 +569,7 @@ static int write_tree( GITERR_CHECK_ALLOC(subdir); /* Write out the subtree */ - written = write_tree(&sub_oid, repo, index, subdir, i); + written = write_tree(&sub_oid, repo, index, subdir, i, shared_buf); if (written < 0) { git__free(subdir); goto on_error; @@ -600,7 +601,7 @@ static int write_tree( } } - if (git_treebuilder_write(oid, bld) < 0) + if (git_treebuilder_write_with_buffer(oid, bld, shared_buf) < 0) goto on_error; git_treebuilder_free(bld); @@ -616,6 +617,7 @@ int git_tree__write_index( { int ret; git_tree *tree; + git_buf shared_buf = GIT_BUF_INIT; bool old_ignore_case = false; assert(oid && index && repo); @@ -641,7 +643,8 @@ int git_tree__write_index( git_index__set_ignore_case(index, false); } - ret = write_tree(oid, repo, index, "", 0); + ret = write_tree(oid, repo, index, "", 0, &shared_buf); + git_buf_free(&shared_buf); if (old_ignore_case) git_index__set_ignore_case(index, true); @@ -796,20 +799,37 @@ int git_treebuilder_remove(git_treebuilder *bld, const char *filename) } int git_treebuilder_write(git_oid *oid, git_treebuilder *bld) +{ + int error; + git_buf buffer = GIT_BUF_INIT; + + error = git_treebuilder_write_with_buffer(oid, bld, &buffer); + + git_buf_free(&buffer); + return error; +} + +int git_treebuilder_write_with_buffer(git_oid *oid, git_treebuilder *bld, git_buf *tree) { int error = 0; size_t i, entrycount; - git_buf tree = GIT_BUF_INIT; git_odb *odb; git_tree_entry *entry; git_vector entries; assert(bld); + assert(tree); + + git_buf_clear(tree); entrycount = git_strmap_num_entries(bld->map); if (git_vector_init(&entries, entrycount, entry_sort_cmp) < 0) return -1; + if (tree->asize == 0 && + (error = git_buf_grow(tree, entrycount * 72)) < 0) + return error; + git_strmap_foreach_value(bld->map, entry, { if (git_vector_insert(&entries, entry) < 0) return -1; @@ -817,26 +837,21 @@ int git_treebuilder_write(git_oid *oid, git_treebuilder *bld) git_vector_sort(&entries); - /* Grow the buffer beforehand to an estimated size */ - error = git_buf_grow(&tree, entrycount * 72); - 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); - git_buf_put(&tree, (char *)entry->oid->id, GIT_OID_RAWSZ); + git_buf_printf(tree, "%o ", entry->attr); + git_buf_put(tree, entry->filename, entry->filename_len + 1); + git_buf_put(tree, (char *)entry->oid->id, GIT_OID_RAWSZ); - if (git_buf_oom(&tree)) + if (git_buf_oom(tree)) error = -1; } - if (!error && !(error = git_repository_odb__weakptr(&odb, bld->repo))) - error = git_odb_write(oid, odb, tree.ptr, tree.size, GIT_OBJ_TREE); + error = git_odb_write(oid, odb, tree->ptr, tree->size, GIT_OBJ_TREE); - git_buf_free(&tree); git_vector_free(&entries); return error; From 567b83de5434abcc40eeeabb8167979240f27a8f Mon Sep 17 00:00:00 2001 From: Nurahmadie Date: Sat, 24 Dec 2016 17:43:08 +0700 Subject: [PATCH 010/366] Fix BIO_* functions method linking when compiled with libressl. ref: https://github.com/gentoo/libressl/blob/672ac74ce7b7cb2e4799b2d66bc0b1b1efa3454e/media-video/ffmpeg/files/ffmpeg-3.2-libressl.patch --- src/openssl_stream.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/openssl_stream.h b/src/openssl_stream.h index b769437ae..f5e59dab1 100644 --- a/src/openssl_stream.h +++ b/src/openssl_stream.h @@ -27,7 +27,7 @@ extern int git_openssl_stream_new(git_stream **out, const char *host, const char -# if OPENSSL_VERSION_NUMBER < 0x10100000L +# if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) GIT_INLINE(BIO_METHOD*) BIO_meth_new(int type, const char *name) { From 6a8127d71d10d5b2d7adfda3da1182568e19afde Mon Sep 17 00:00:00 2001 From: Jacques Germishuys Date: Sun, 25 Dec 2016 22:13:48 +0200 Subject: [PATCH 011/366] mempack: set the odb backend version --- src/odb_mempack.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/odb_mempack.c b/src/odb_mempack.c index 68db3bc32..84ed9c104 100644 --- a/src/odb_mempack.c +++ b/src/odb_mempack.c @@ -177,6 +177,7 @@ int git_mempack_new(git_odb_backend **out) db->objects = git_oidmap_alloc(); + db->parent.version = GIT_ODB_BACKEND_VERSION; db->parent.read = &impl__read; db->parent.write = &impl__write; db->parent.read_header = &impl__read_header; From f928c69a07168b1236be13b61a6dcb3ecb7a0871 Mon Sep 17 00:00:00 2001 From: Jacques Germishuys Date: Thu, 29 Dec 2016 12:54:26 +0200 Subject: [PATCH 012/366] rebase: check the result code of rebase_init_merge --- src/rebase.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rebase.c b/src/rebase.c index 0af2b3cf4..ef044692a 100644 --- a/src/rebase.c +++ b/src/rebase.c @@ -731,7 +731,7 @@ int git_rebase_init( if (inmemory) error = rebase_init_inmemory(rebase, repo, branch, upstream, onto); else - rebase_init_merge(rebase, repo, branch ,upstream, onto); + error = rebase_init_merge(rebase, repo, branch ,upstream, onto); if (error == 0) *out = rebase; From 909d5494368a00809bc42f4780e86f4dd66e4422 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 29 Dec 2016 12:25:15 +0000 Subject: [PATCH 013/366] giterr_set: consistent error messages Error messages should be sentence fragments, and therefore: 1. Should not begin with a capital letter, 2. Should not conclude with punctuation, and 3. Should not end a sentence and begin a new one --- src/apply.c | 4 +- src/attr_file.c | 10 +-- src/attrcache.c | 6 +- src/blob.c | 6 +- src/branch.c | 20 +++--- src/buffer.c | 8 +-- src/cache.c | 2 +- src/checkout.c | 50 +++++++-------- src/cherrypick.c | 4 +- src/commit.c | 4 +- src/commit_list.c | 4 +- src/common.h | 2 +- src/config.c | 24 +++---- src/config_file.c | 18 +++--- src/crlf.c | 2 +- src/delta.c | 8 +-- src/describe.c | 22 +++---- src/diff_driver.c | 2 +- src/diff_file.c | 2 +- src/diff_generate.c | 4 +- src/diff_print.c | 10 +-- src/diff_tform.c | 2 +- src/diff_xdiff.c | 4 +- src/fetch.c | 2 +- src/fetchhead.c | 16 ++--- src/filebuf.c | 18 +++--- src/fileops.c | 54 ++++++++-------- src/filter.c | 8 +-- src/hashsig.c | 4 +- src/ignore.c | 2 +- src/index.c | 30 ++++----- src/indexer.c | 6 +- src/merge.c | 16 ++--- src/merge_file.c | 2 +- src/mwindow.c | 2 +- src/netops.c | 8 +-- src/notes.c | 6 +- src/object.c | 10 +-- src/odb.c | 24 +++---- src/odb_loose.c | 12 ++-- src/oid.c | 10 +-- src/openssl_stream.c | 6 +- src/pack-objects.c | 10 +-- src/pack.c | 12 ++-- src/patch_generate.c | 4 +- src/path.c | 30 ++++----- src/pathspec.c | 4 +- src/posix.c | 2 +- src/push.c | 12 ++-- src/rebase.c | 24 +++---- src/refdb.c | 2 +- src/refdb_fs.c | 24 +++---- src/reflog.c | 4 +- src/refs.c | 22 +++---- src/remote.c | 6 +- src/repository.c | 26 ++++---- src/repository.h | 2 +- src/reset.c | 2 +- src/revert.c | 4 +- src/revparse.c | 10 +-- src/revwalk.c | 6 +- src/settings.c | 2 +- src/sha1_lookup.c | 2 +- src/signature.c | 2 +- src/socket_stream.c | 10 +-- src/sortedcache.c | 10 +-- src/stash.c | 12 ++-- src/status.c | 8 +-- src/submodule.c | 28 ++++----- src/sysdir.c | 4 +- src/tag.c | 28 ++++----- src/trace.c | 2 +- src/transport.c | 2 +- src/transports/auth_negotiate.c | 8 +-- src/transports/cred.c | 2 +- src/transports/git.c | 6 +- src/transports/http.c | 12 ++-- src/transports/local.c | 4 +- src/transports/smart.c | 10 +-- src/transports/smart_pkt.c | 8 +-- src/transports/smart_protocol.c | 2 +- src/transports/ssh.c | 18 +++--- src/transports/winhttp.c | 100 +++++++++++++++--------------- src/tree-cache.c | 4 +- src/tree.c | 10 +-- src/unix/map.c | 2 +- src/util.c | 6 +- src/win32/dir.c | 6 +- src/win32/findfile.c | 2 +- src/win32/map.c | 12 ++-- src/win32/w32_crtdbg_stacktrace.c | 4 +- src/win32/w32_util.c | 2 +- src/win32/w32_util.h | 2 +- src/zstream.c | 2 +- 94 files changed, 496 insertions(+), 496 deletions(-) diff --git a/src/apply.c b/src/apply.c index 635934299..595f5f300 100644 --- a/src/apply.c +++ b/src/apply.c @@ -173,7 +173,7 @@ static int apply_hunk( git_diff_line *line = git_array_get(patch->lines, linenum); if (!line) { - error = apply_err("Preimage does not contain line %"PRIuZ, linenum); + error = apply_err("preimage does not contain line %"PRIuZ, linenum); goto done; } @@ -193,7 +193,7 @@ static int apply_hunk( line_num = hunk->hunk.new_start ? hunk->hunk.new_start - 1 : 0; if (!find_hunk_linenum(&line_num, image, &preimage, line_num)) { - error = apply_err("Hunk at line %d did not apply", + error = apply_err("hunk at line %d did not apply", hunk->hunk.new_start); goto done; } diff --git a/src/attr_file.c b/src/attr_file.c index 11d149358..0bb761d04 100644 --- a/src/attr_file.c +++ b/src/attr_file.c @@ -30,7 +30,7 @@ int git_attr_file__new( GITERR_CHECK_ALLOC(attrs); if (git_mutex_init(&attrs->lock) < 0) { - giterr_set(GITERR_OS, "Failed to initialize lock"); + giterr_set(GITERR_OS, "failed to initialize lock"); git__free(attrs); return -1; } @@ -49,7 +49,7 @@ int git_attr_file__clear_rules(git_attr_file *file, bool need_lock) git_attr_rule *rule; if (need_lock && git_mutex_lock(&file->lock) < 0) { - giterr_set(GITERR_OS, "Failed to lock attribute file"); + giterr_set(GITERR_OS, "failed to lock attribute file"); return -1; } @@ -140,7 +140,7 @@ int git_attr_file__load( break; } default: - giterr_set(GITERR_INVALID, "Unknown file source %d", source); + giterr_set(GITERR_INVALID, "unknown file source %d", source); return -1; } @@ -212,7 +212,7 @@ int git_attr_file__out_of_date( } default: - giterr_set(GITERR_INVALID, "Invalid file type %d", file->source); + giterr_set(GITERR_INVALID, "invalid file type %d", file->source); return -1; } } @@ -238,7 +238,7 @@ int git_attr_file__parse_buffer( context = attrs->entry->path; if (git_mutex_lock(&attrs->lock) < 0) { - giterr_set(GITERR_OS, "Failed to lock attribute file"); + giterr_set(GITERR_OS, "failed to lock attribute file"); return -1; } diff --git a/src/attrcache.c b/src/attrcache.c index a57110684..0ade38c7c 100644 --- a/src/attrcache.c +++ b/src/attrcache.c @@ -12,7 +12,7 @@ GIT_INLINE(int) attr_cache_lock(git_attr_cache *cache) GIT_UNUSED(cache); /* avoid warning if threading is off */ if (git_mutex_lock(&cache->lock) < 0) { - giterr_set(GITERR_OS, "Unable to get attr cache lock"); + giterr_set(GITERR_OS, "unable to get attr cache lock"); return -1; } return 0; @@ -365,7 +365,7 @@ int git_attr_cache__do_init(git_repository *repo) /* set up lock */ if (git_mutex_init(&cache->lock) < 0) { - giterr_set(GITERR_OS, "Unable to initialize lock for attr cache"); + giterr_set(GITERR_OS, "unable to initialize lock for attr cache"); git__free(cache); return -1; } @@ -430,7 +430,7 @@ int git_attr_cache__insert_macro(git_repository *repo, git_attr_rule *macro) return 0; if (git_mutex_lock(&cache->lock) < 0) { - giterr_set(GITERR_OS, "Unable to get attr cache lock"); + giterr_set(GITERR_OS, "unable to get attr cache lock"); error = -1; } else { git_strmap_insert(macros, macro->match.pattern, macro, error); diff --git a/src/blob.c b/src/blob.c index 1926c9e58..cd5df3537 100644 --- a/src/blob.c +++ b/src/blob.c @@ -96,7 +96,7 @@ static int write_file_stream( p_close(fd); if (written != file_size || read_len < 0) { - giterr_set(GITERR_OS, "Failed to read file into stream"); + giterr_set(GITERR_OS, "failed to read file into stream"); error = -1; } @@ -142,7 +142,7 @@ static int write_symlink( read_len = p_readlink(path, link_data, link_size); if (read_len != (ssize_t)link_size) { - giterr_set(GITERR_OS, "Failed to create blob. Can't read symlink '%s'", path); + giterr_set(GITERR_OS, "failed to create blob: cannot read symlink '%s'", path); git__free(link_data); return -1; } @@ -186,7 +186,7 @@ int git_blob__create_from_paths( goto done; if (S_ISDIR(st.st_mode)) { - giterr_set(GITERR_ODB, "cannot create blob from '%s'; it is a directory", content_path); + giterr_set(GITERR_ODB, "cannot create blob from '%s': it is a directory", content_path); error = GIT_EDIRECTORY; goto done; } diff --git a/src/branch.c b/src/branch.c index 8d1ed6577..7ddcb3da7 100644 --- a/src/branch.c +++ b/src/branch.c @@ -33,7 +33,7 @@ static int retrieve_branch_reference( /* OOM */; else if ((error = git_reference_lookup(&branch, repo, ref_name.ptr)) < 0) giterr_set( - GITERR_REFERENCE, "Cannot locate %s branch '%s'", + GITERR_REFERENCE, "cannot locate %s branch '%s'", is_remote ? "remote-tracking" : "local", branch_name); *branch_reference_out = branch; /* will be NULL on error */ @@ -46,7 +46,7 @@ static int not_a_local_branch(const char *reference_name) { giterr_set( GITERR_INVALID, - "Reference '%s' is not a local branch.", reference_name); + "reference '%s' is not a local branch.", reference_name); return -1; } @@ -80,7 +80,7 @@ static int create_branch( } if (is_unmovable_head && force) { - giterr_set(GITERR_REFERENCE, "Cannot force update branch '%s' as it is " + giterr_set(GITERR_REFERENCE, "cannot force update branch '%s' as it is " "the current HEAD of the repository.", branch_name); error = -1; goto cleanup; @@ -135,7 +135,7 @@ int git_branch_delete(git_reference *branch) assert(branch); if (!git_reference_is_branch(branch) && !git_reference_is_remote(branch)) { - giterr_set(GITERR_INVALID, "Reference '%s' is not a valid branch.", + giterr_set(GITERR_INVALID, "reference '%s' is not a valid branch.", git_reference_name(branch)); return GIT_ENOTFOUND; } @@ -144,7 +144,7 @@ int git_branch_delete(git_reference *branch) return is_head; if (is_head) { - giterr_set(GITERR_REFERENCE, "Cannot delete branch '%s' as it is " + giterr_set(GITERR_REFERENCE, "cannot delete branch '%s' as it is " "the current HEAD of the repository.", git_reference_name(branch)); return -1; } @@ -306,7 +306,7 @@ int git_branch_name( branch_name += strlen(GIT_REFS_REMOTES_DIR); } else { giterr_set(GITERR_INVALID, - "Reference '%s' is neither a local nor a remote branch.", ref->name); + "reference '%s' is neither a local nor a remote branch.", ref->name); return -1; } *out = branch_name; @@ -436,7 +436,7 @@ int git_branch_remote_name(git_buf *buf, git_repository *repo, const char *refna /* Verify that this is a remote branch */ if (!git_reference__is_remote(refname)) { - giterr_set(GITERR_INVALID, "Reference '%s' is not a remote branch.", + giterr_set(GITERR_INVALID, "reference '%s' is not a remote branch.", refname); error = GIT_ERROR; goto cleanup; @@ -463,7 +463,7 @@ int git_branch_remote_name(git_buf *buf, git_repository *repo, const char *refna git_remote_free(remote); giterr_set(GITERR_REFERENCE, - "Reference '%s' is ambiguous", refname); + "reference '%s' is ambiguous", refname); error = GIT_EAMBIGUOUS; goto cleanup; } @@ -477,7 +477,7 @@ int git_branch_remote_name(git_buf *buf, git_repository *repo, const char *refna error = git_buf_puts(buf, remote_name); } else { giterr_set(GITERR_REFERENCE, - "Could not determine remote for '%s'", refname); + "could not determine remote for '%s'", refname); error = GIT_ENOTFOUND; } @@ -566,7 +566,7 @@ int git_branch_set_upstream(git_reference *branch, const char *upstream_name) local = 0; else { giterr_set(GITERR_REFERENCE, - "Cannot set upstream for branch '%s'", shortname); + "cannot set upstream for branch '%s'", shortname); return GIT_ENOTFOUND; } diff --git a/src/buffer.c b/src/buffer.c index d135ebe4a..fdb732d9e 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -962,14 +962,14 @@ int git_buf_unquote(git_buf *buf) case '0': case '1': case '2': case '3': if (j == buf->size-3) { giterr_set(GITERR_INVALID, - "Truncated quoted character \\%c", ch); + "truncated quoted character \\%c", ch); return -1; } if (buf->ptr[j+1] < '0' || buf->ptr[j+1] > '7' || buf->ptr[j+2] < '0' || buf->ptr[j+2] > '7') { giterr_set(GITERR_INVALID, - "Truncated quoted character \\%c%c%c", + "truncated quoted character \\%c%c%c", buf->ptr[j], buf->ptr[j+1], buf->ptr[j+2]); return -1; } @@ -981,7 +981,7 @@ int git_buf_unquote(git_buf *buf) break; default: - giterr_set(GITERR_INVALID, "Invalid quoted character \\%c", ch); + giterr_set(GITERR_INVALID, "invalid quoted character \\%c", ch); return -1; } } @@ -995,6 +995,6 @@ int git_buf_unquote(git_buf *buf) return 0; invalid: - giterr_set(GITERR_INVALID, "Invalid quoted line"); + giterr_set(GITERR_INVALID, "invalid quoted line"); return -1; } diff --git a/src/cache.c b/src/cache.c index ca5173c0d..16ae9b397 100644 --- a/src/cache.c +++ b/src/cache.c @@ -70,7 +70,7 @@ int git_cache_init(git_cache *cache) cache->map = git_oidmap_alloc(); GITERR_CHECK_ALLOC(cache->map); if (git_rwlock_init(&cache->lock)) { - giterr_set(GITERR_OS, "Failed to initialize cache rwlock"); + giterr_set(GITERR_OS, "failed to initialize cache rwlock"); return -1; } return 0; diff --git a/src/checkout.c b/src/checkout.c index 62950913e..0cc29054d 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -1021,13 +1021,13 @@ static int checkout_conflicts_load_byname_entry( *theirs_out = NULL; if (!name_entry->ancestor) { - giterr_set(GITERR_INDEX, "A NAME entry exists without an ancestor"); + giterr_set(GITERR_INDEX, "a NAME entry exists without an ancestor"); error = -1; goto done; } if (!name_entry->ours && !name_entry->theirs) { - giterr_set(GITERR_INDEX, "A NAME entry exists without an ours or theirs"); + giterr_set(GITERR_INDEX, "a NAME entry exists without an ours or theirs"); error = -1; goto done; } @@ -1035,7 +1035,7 @@ static int checkout_conflicts_load_byname_entry( if ((ancestor = checkout_conflicts_search_ancestor(data, name_entry->ancestor)) == NULL) { giterr_set(GITERR_INDEX, - "A NAME entry referenced ancestor entry '%s' which does not exist in the main index", + "a NAME entry referenced ancestor entry '%s' which does not exist in the main index", name_entry->ancestor); error = -1; goto done; @@ -1047,7 +1047,7 @@ static int checkout_conflicts_load_byname_entry( else if ((ours = checkout_conflicts_search_branch(data, name_entry->ours)) == NULL || ours->ours == NULL) { giterr_set(GITERR_INDEX, - "A NAME entry referenced our entry '%s' which does not exist in the main index", + "a NAME entry referenced our entry '%s' which does not exist in the main index", name_entry->ours); error = -1; goto done; @@ -1062,7 +1062,7 @@ static int checkout_conflicts_load_byname_entry( else if ((theirs = checkout_conflicts_search_branch(data, name_entry->theirs)) == NULL || theirs->theirs == NULL) { giterr_set(GITERR_INDEX, - "A NAME entry referenced their entry '%s' which does not exist in the main index", + "a NAME entry referenced their entry '%s' which does not exist in the main index", name_entry->theirs); error = -1; goto done; @@ -1161,7 +1161,7 @@ static int checkout_conflicts_mark_directoryfile( 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); + "index inconsistency, could not find entry for expected conflict '%s'", path); goto done; } @@ -1169,7 +1169,7 @@ static int checkout_conflicts_mark_directoryfile( for (; j < len; j++) { if ((entry = git_index_get_byindex(index, j)) == NULL) { giterr_set(GITERR_INDEX, - "Index inconsistency, truncated index while loading expected conflict '%s'", path); + "index inconsistency, truncated index while loading expected conflict '%s'", path); error = -1; goto done; } @@ -1254,14 +1254,14 @@ static int checkout_verify_paths( if (action & CHECKOUT_ACTION__REMOVE) { if (!git_path_isvalid(repo, delta->old_file.path, flags)) { - giterr_set(GITERR_CHECKOUT, "Cannot remove invalid path '%s'", delta->old_file.path); + giterr_set(GITERR_CHECKOUT, "cannot remove invalid path '%s'", delta->old_file.path); return -1; } } if (action & ~CHECKOUT_ACTION__REMOVE) { if (!git_path_isvalid(repo, delta->new_file.path, flags)) { - giterr_set(GITERR_CHECKOUT, "Cannot checkout to invalid path '%s'", delta->new_file.path); + giterr_set(GITERR_CHECKOUT, "cannot checkout to invalid path '%s'", delta->new_file.path); return -1; } } @@ -1430,7 +1430,7 @@ static int mkpath2file( */ error = git_futils_rmdir_r(path, NULL, GIT_RMDIR_REMOVE_FILES); } else if (errno != ENOENT) { - giterr_set(GITERR_OS, "Failed to stat file '%s'", path); + giterr_set(GITERR_OS, "failed to stat '%s'", path); return GIT_EEXISTS; } else { giterr_clear(); @@ -1454,7 +1454,7 @@ static int checkout_stream_write( int ret; if ((ret = p_write(stream->fd, buffer, len)) < 0) - giterr_set(GITERR_OS, "Could not write to '%s'", stream->path); + giterr_set(GITERR_OS, "could not write to '%s'", stream->path); return ret; } @@ -1503,7 +1503,7 @@ static int blob_content_to_file( mode = GIT_FILEMODE_BLOB; if ((fd = p_open(path, flags, mode)) < 0) { - giterr_set(GITERR_OS, "Could not open '%s' for writing", path); + giterr_set(GITERR_OS, "could not open '%s' for writing", path); return fd; } @@ -1540,7 +1540,7 @@ static int blob_content_to_file( data->perfdata.stat_calls++; if ((error = p_stat(path, st)) < 0) { - giterr_set(GITERR_OS, "Error statting '%s'", path); + giterr_set(GITERR_OS, "failed to stat '%s'", path); return error; } @@ -1567,7 +1567,7 @@ static int blob_content_to_link( if (data->can_symlink) { if ((error = p_symlink(git_buf_cstr(&linktarget), path)) < 0) - giterr_set(GITERR_OS, "Could not create symlink %s", path); + giterr_set(GITERR_OS, "could not create symlink %s", path); } else { error = git_futils_fake_symlink(git_buf_cstr(&linktarget), path); } @@ -1576,7 +1576,7 @@ static int blob_content_to_link( data->perfdata.stat_calls++; if ((error = p_lstat(path, st)) < 0) - giterr_set(GITERR_CHECKOUT, "Could not stat symlink %s", path); + giterr_set(GITERR_CHECKOUT, "could not stat symlink %s", path); st->st_mode = GIT_FILEMODE_LINK; } @@ -1621,7 +1621,7 @@ static int checkout_submodule_update_index( data->perfdata.stat_calls++; if (p_stat(fullpath->ptr, &st) < 0) { giterr_set( - GITERR_CHECKOUT, "Could not stat submodule %s\n", file->path); + GITERR_CHECKOUT, "could not stat submodule %s\n", file->path); return GIT_ENOTFOUND; } @@ -1694,7 +1694,7 @@ static int checkout_safe_for_update_only( return 0; /* otherwise, stat error and no update */ - giterr_set(GITERR_OS, "Failed to stat file '%s'", path); + giterr_set(GITERR_OS, "failed to stat '%s'", path); return -1; } @@ -1966,7 +1966,7 @@ static int checkout_path_suffixed(git_buf *path, const char *suffix) if (i == INT_MAX) { git_buf_truncate(path, path_len); - giterr_set(GITERR_CHECKOUT, "Could not write '%s': working directory file exists", path->ptr); + giterr_set(GITERR_CHECKOUT, "could not write '%s': working directory file exists", path->ptr); return GIT_EEXISTS; } @@ -2097,7 +2097,7 @@ static int checkout_write_merge( goto done; if (result.path == NULL || result.mode == 0) { - giterr_set(GITERR_CHECKOUT, "Could not merge contents of file"); + giterr_set(GITERR_CHECKOUT, "could not merge contents of file"); error = GIT_ECONFLICT; goto done; } @@ -2345,7 +2345,7 @@ static int checkout_data_init( memset(data, 0, sizeof(*data)); if (!repo) { - giterr_set(GITERR_CHECKOUT, "Cannot checkout nothing"); + giterr_set(GITERR_CHECKOUT, "cannot checkout nothing"); return -1; } @@ -2647,7 +2647,7 @@ int git_checkout_index( if (!index && !repo) { giterr_set(GITERR_CHECKOUT, - "Must provide either repository or index to checkout"); + "must provide either repository or index to checkout"); return -1; } @@ -2655,7 +2655,7 @@ int git_checkout_index( git_index_owner(index) && git_index_owner(index) != repo) { giterr_set(GITERR_CHECKOUT, - "Index to checkout does not match repository"); + "index to checkout does not match repository"); return -1; } else if(index && repo && !git_index_owner(index)) { GIT_REFCOUNT_OWN(index, repo); @@ -2694,12 +2694,12 @@ int git_checkout_tree( if (!treeish && !repo) { giterr_set(GITERR_CHECKOUT, - "Must provide either repository or tree to checkout"); + "must provide either repository or tree to checkout"); return -1; } if (treeish && repo && git_object_owner(treeish) != repo) { giterr_set(GITERR_CHECKOUT, - "Object to checkout does not match repository"); + "object to checkout does not match repository"); return -1; } @@ -2709,7 +2709,7 @@ int git_checkout_tree( if (treeish) { if (git_object_peel((git_object **)&tree, treeish, GIT_OBJ_TREE) < 0) { giterr_set( - GITERR_CHECKOUT, "Provided object cannot be peeled to a tree"); + GITERR_CHECKOUT, "provided object cannot be peeled to a tree"); return -1; } } diff --git a/src/cherrypick.c b/src/cherrypick.c index c92975194..ab067339e 100644 --- a/src/cherrypick.c +++ b/src/cherrypick.c @@ -130,13 +130,13 @@ int git_cherrypick_commit( if (git_commit_parentcount(cherrypick_commit) > 1) { if (!mainline) return cherrypick_seterr(cherrypick_commit, - "Mainline branch is not specified but %s is a merge commit"); + "mainline branch is not specified but %s is a merge commit"); parent = mainline; } else { if (mainline) return cherrypick_seterr(cherrypick_commit, - "Mainline branch specified but %s is not a merge commit"); + "mainline branch specified but %s is not a merge commit"); parent = git_commit_parentcount(cherrypick_commit); } diff --git a/src/commit.c b/src/commit.c index 76e6dcbc9..87ab2ab60 100644 --- a/src/commit.c +++ b/src/commit.c @@ -468,7 +468,7 @@ int git_commit__parse(void *_commit, git_odb_object *odb_obj) return 0; bad_buffer: - giterr_set(GITERR_OBJECT, "Failed to parse bad commit object"); + giterr_set(GITERR_OBJECT, "failed to parse bad commit object"); return -1; } @@ -598,7 +598,7 @@ int git_commit_parent( parent_id = git_commit_parent_id(commit, n); if (parent_id == NULL) { - giterr_set(GITERR_INVALID, "Parent %u does not exist", n); + giterr_set(GITERR_INVALID, "parent %u does not exist", n); return GIT_ENOTFOUND; } diff --git a/src/commit_list.c b/src/commit_list.c index a1681ffae..3bba58c27 100644 --- a/src/commit_list.c +++ b/src/commit_list.c @@ -61,7 +61,7 @@ static int commit_error(git_commit_list_node *commit, const char *msg) git_oid_fmt(commit_oid, &commit->oid); commit_oid[GIT_OID_HEXSZ] = '\0'; - giterr_set(GITERR_ODB, "Failed to parse commit %s - %s", commit_oid, msg); + giterr_set(GITERR_ODB, "failed to parse commit %s - %s", commit_oid, msg); return -1; } @@ -191,7 +191,7 @@ int git_commit_list_parse(git_revwalk *walk, git_commit_list_node *commit) return error; if (obj->cached.type != GIT_OBJ_COMMIT) { - giterr_set(GITERR_INVALID, "Object is no commit object"); + giterr_set(GITERR_INVALID, "object is no commit object"); error = -1; } else error = commit_quick_parse( diff --git a/src/common.h b/src/common.h index f12cc98cf..e566aeabd 100644 --- a/src/common.h +++ b/src/common.h @@ -188,7 +188,7 @@ GIT_INLINE(int) giterr__check_version(const void *structure, unsigned int expect if (actual > 0 && actual <= expected_max) return 0; - giterr_set(GITERR_INVALID, "Invalid version %d on %s", actual, name); + giterr_set(GITERR_INVALID, "invalid version %d on %s", actual, name); return -1; } #define GITERR_CHECK_VERSION(S,V,N) if (giterr__check_version(S,V,N) < 0) return -1 diff --git a/src/config.c b/src/config.c index 403b7090d..0d73ad2cc 100644 --- a/src/config.c +++ b/src/config.c @@ -109,7 +109,7 @@ int git_config_add_file_ondisk( res = p_stat(path, &st); if (res < 0 && errno != ENOENT) { - giterr_set(GITERR_CONFIG, "Error stat'ing config file '%s'", path); + giterr_set(GITERR_CONFIG, "failed to stat '%s'", path); return -1; } @@ -203,7 +203,7 @@ static int find_internal_file_by_level( if (pos == -1) { giterr_set(GITERR_CONFIG, - "No config file exists for the given level '%i'", (int)level); + "no config file exists for the given level '%i'", (int)level); return GIT_ENOTFOUND; } @@ -218,7 +218,7 @@ static int duplicate_level(void **old_raw, void *new_raw) GIT_UNUSED(new_raw); - giterr_set(GITERR_CONFIG, "A file with the same level (%i) has already been added to the config", (int)(*old)->level); + giterr_set(GITERR_CONFIG, "a file with the same level (%i) has already been added to the config", (int)(*old)->level); return GIT_EEXISTS; } @@ -579,7 +579,7 @@ int git_config_foreach_match( static int config_error_nofiles(const char *name) { giterr_set(GITERR_CONFIG, - "Cannot set value for '%s' when no config files exist", name); + "cannot set value for '%s' when no config files exist", name); return GIT_ENOTFOUND; } @@ -620,7 +620,7 @@ int git_config_set_string(git_config *cfg, const char *name, const char *value) file_internal *internal; if (!value) { - giterr_set(GITERR_CONFIG, "The value to set cannot be NULL"); + giterr_set(GITERR_CONFIG, "the value to set cannot be NULL"); return -1; } @@ -674,7 +674,7 @@ int git_config__update_entry( static int config_error_notfound(const char *name) { - giterr_set(GITERR_CONFIG, "Config value '%s' was not found", name); + giterr_set(GITERR_CONFIG, "config value '%s' was not found", name); return GIT_ENOTFOUND; } @@ -1236,7 +1236,7 @@ int git_config_lookup_map_value( } fail_parse: - giterr_set(GITERR_CONFIG, "Failed to map '%s'", value); + giterr_set(GITERR_CONFIG, "failed to map '%s'", value); return -1; } @@ -1270,7 +1270,7 @@ int git_config_parse_bool(int *out, const char *value) return 0; } - giterr_set(GITERR_CONFIG, "Failed to parse '%s' as a boolean value", value); + giterr_set(GITERR_CONFIG, "failed to parse '%s' as a boolean value", value); return -1; } @@ -1313,7 +1313,7 @@ int git_config_parse_int64(int64_t *out, const char *value) } fail_parse: - giterr_set(GITERR_CONFIG, "Failed to parse '%s' as an integer", value ? value : "(null)"); + giterr_set(GITERR_CONFIG, "failed to parse '%s' as an integer", value ? value : "(null)"); return -1; } @@ -1333,7 +1333,7 @@ int git_config_parse_int32(int32_t *out, const char *value) return 0; fail_parse: - giterr_set(GITERR_CONFIG, "Failed to parse '%s' as a 32-bit integer", value ? value : "(null)"); + giterr_set(GITERR_CONFIG, "failed to parse '%s' as a 32-bit integer", value ? value : "(null)"); return -1; } @@ -1398,7 +1398,7 @@ int git_config__normalize_name(const char *in, char **out) invalid: git__free(name); - giterr_set(GITERR_CONFIG, "Invalid config item name '%s'", in); + giterr_set(GITERR_CONFIG, "invalid config item name '%s'", in); return GIT_EINVALIDSPEC; } @@ -1461,7 +1461,7 @@ int git_config_rename_section( replace.ptr, strchr(replace.ptr, '.'))) < 0) { giterr_set( - GITERR_CONFIG, "Invalid config section '%s'", new_section_name); + GITERR_CONFIG, "invalid config section '%s'", new_section_name); goto cleanup; } diff --git a/src/config_file.c b/src/config_file.c index 9ff021e7e..2e3d568bb 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -126,7 +126,7 @@ static int config_snapshot(git_config_backend **out, git_config_backend *in); static void set_parse_error(struct reader *reader, int col, const char *error_str) { - giterr_set(GITERR_CONFIG, "Failed to parse config file: %s (in %s:%d, column %d)", + giterr_set(GITERR_CONFIG, "failed to parse config file: %s (in %s:%d, column %d)", error_str, reader->file_path, reader->line_number, col); } @@ -233,7 +233,7 @@ static refcounted_strmap *refcounted_strmap_take(diskfile_header *h) refcounted_strmap *map; if (git_mutex_lock(&h->values_mutex) < 0) { - giterr_set(GITERR_OS, "Failed to lock config backend"); + giterr_set(GITERR_OS, "failed to lock config backend"); return NULL; } @@ -322,7 +322,7 @@ static int config__refresh(git_config_backend *cfg) goto out; if ((error = git_mutex_lock(&b->header.values_mutex)) < 0) { - giterr_set(GITERR_OS, "Failed to lock config backend"); + giterr_set(GITERR_OS, "failed to lock config backend"); goto out; } @@ -479,7 +479,7 @@ static int config_set(git_config_backend *cfg, const char *name, const char *val cvar_t *existing = git_strmap_value_at(values, pos); if (existing->next != NULL) { - giterr_set(GITERR_CONFIG, "Multivar incompatible with simple set"); + giterr_set(GITERR_CONFIG, "multivar incompatible with simple set"); ret = -1; goto out; } @@ -611,7 +611,7 @@ static int config_delete(git_config_backend *cfg, const char *name) if (!git_strmap_valid_index(values, pos)) { refcounted_strmap_free(map); - giterr_set(GITERR_CONFIG, "Could not find key '%s' to delete", name); + giterr_set(GITERR_CONFIG, "could not find key '%s' to delete", name); return GIT_ENOTFOUND; } @@ -619,7 +619,7 @@ static int config_delete(git_config_backend *cfg, const char *name) refcounted_strmap_free(map); if (var->next != NULL) { - giterr_set(GITERR_CONFIG, "Cannot delete multivar with a single delete"); + giterr_set(GITERR_CONFIG, "cannot delete multivar with a single delete"); return -1; } @@ -651,7 +651,7 @@ static int config_delete_multivar(git_config_backend *cfg, const char *name, con if (!git_strmap_valid_index(values, pos)) { refcounted_strmap_free(map); git__free(key); - giterr_set(GITERR_CONFIG, "Could not find key '%s' to delete", name); + giterr_set(GITERR_CONFIG, "could not find key '%s' to delete", name); return GIT_ENOTFOUND; } @@ -1325,7 +1325,7 @@ static int unescape_line( *fixed++ = escaped[esc - escapes]; } else { git__free(str); - giterr_set(GITERR_CONFIG, "Invalid escape at %s", ptr); + giterr_set(GITERR_CONFIG, "invalid escape at %s", ptr); return -1; } } @@ -1639,7 +1639,7 @@ static int config_read(git_strmap *values, diskfile_backend *cfg_file, struct re struct parse_data parse_data; if (depth >= MAX_INCLUDE_DEPTH) { - giterr_set(GITERR_CONFIG, "Maximum config include depth reached"); + giterr_set(GITERR_CONFIG, "maximum config include depth reached"); return -1; } diff --git a/src/crlf.c b/src/crlf.c index 11895b19f..b8ae5cda1 100644 --- a/src/crlf.c +++ b/src/crlf.c @@ -218,7 +218,7 @@ static const char *line_ending(struct crlf_attrs *ca) return "\r\n"; line_ending_error: - giterr_set(GITERR_INVALID, "Invalid input to line ending filter"); + giterr_set(GITERR_INVALID, "invalid input to line ending filter"); return NULL; } diff --git a/src/delta.c b/src/delta.c index dc45697b6..073cba7c6 100644 --- a/src/delta.c +++ b/src/delta.c @@ -131,7 +131,7 @@ static int lookup_index_alloc( GITERR_CHECK_ALLOC_ADD(&index_len, index_len, hash_len); if (!git__is_ulong(index_len)) { - giterr_set(GITERR_NOMEMORY, "Overly large delta"); + giterr_set(GITERR_NOMEMORY, "overly large delta"); return -1; } @@ -544,12 +544,12 @@ int git_delta_apply( * base object, resulting in data corruption or segfault. */ if ((hdr_sz(&base_sz, &delta, delta_end) < 0) || (base_sz != base_len)) { - giterr_set(GITERR_INVALID, "Failed to apply delta. Base size does not match given data"); + giterr_set(GITERR_INVALID, "failed to apply delta: base size does not match given data"); return -1; } if (hdr_sz(&res_sz, &delta, delta_end) < 0) { - giterr_set(GITERR_INVALID, "Failed to apply delta. Base size does not match given data"); + giterr_set(GITERR_INVALID, "failed to apply delta: base size does not match given data"); return -1; } @@ -614,6 +614,6 @@ fail: *out = NULL; *out_len = 0; - giterr_set(GITERR_INVALID, "Failed to apply delta"); + giterr_set(GITERR_INVALID, "failed to apply delta"); return -1; } diff --git a/src/describe.c b/src/describe.c index fc48fbde4..16e195542 100644 --- a/src/describe.c +++ b/src/describe.c @@ -335,14 +335,14 @@ static int display_name(git_buf *buf, git_repository *repo, struct commit_name * { if (n->prio == 2 && !n->tag) { if (git_tag_lookup(&n->tag, repo, &n->sha1) < 0) { - giterr_set(GITERR_TAG, "Annotated tag '%s' not available", n->path); + giterr_set(GITERR_TAG, "annotated tag '%s' not available", n->path); return -1; } } if (n->tag && !n->name_checked) { if (!git_tag_name(n->tag)) { - giterr_set(GITERR_TAG, "Annotated tag '%s' has no embedded name", n->path); + giterr_set(GITERR_TAG, "annotated tag '%s' has no embedded name", n->path); return -1; } @@ -471,7 +471,7 @@ static int describe( if (!data->opts->max_candidates_tags) { error = describe_not_found( git_commit_id(commit), - "Cannot describe - no tag exactly matches '%s'"); + "cannot describe - no tag exactly matches '%s'"); goto cleanup; } @@ -564,15 +564,15 @@ static int describe( } if (unannotated_cnt) { error = describe_not_found(git_commit_id(commit), - "Cannot describe - " - "No annotated tags can describe '%s'." - "However, there were unannotated tags."); + "cannot describe - " + "no annotated tags can describe '%s'; " + "however, there were unannotated tags."); goto cleanup; } else { error = describe_not_found(git_commit_id(commit), - "Cannot describe - " - "No tags can describe '%s'."); + "cannot describe - " + "no tags can describe '%s'."); goto cleanup; } } @@ -695,8 +695,8 @@ int git_describe_commit( goto cleanup; if (git_oidmap_size(data.names) == 0 && !opts->show_commit_oid_as_fallback) { - giterr_set(GITERR_DESCRIBE, "Cannot describe - " - "No reference found, cannot describe anything."); + giterr_set(GITERR_DESCRIBE, "cannot describe - " + "no reference found, cannot describe anything."); error = -1; goto cleanup; } @@ -793,7 +793,7 @@ int git_describe_format(git_buf *out, const git_describe_result *result, const g if (opts.always_use_long_format && opts.abbreviated_size == 0) { - giterr_set(GITERR_DESCRIBE, "Cannot describe - " + giterr_set(GITERR_DESCRIBE, "cannot describe - " "'always_use_long_format' is incompatible with a zero" "'abbreviated_size'"); return -1; diff --git a/src/diff_driver.c b/src/diff_driver.c index 1a7f09a44..0adf704fb 100644 --- a/src/diff_driver.c +++ b/src/diff_driver.c @@ -151,7 +151,7 @@ static git_diff_driver_registry *git_repository_driver_registry( } if (!repo->diff_drivers) - giterr_set(GITERR_REPOSITORY, "Unable to create diff driver registry"); + giterr_set(GITERR_REPOSITORY, "unable to create diff driver registry"); return repo->diff_drivers; } diff --git a/src/diff_file.c b/src/diff_file.c index cc1029038..d5fc5e940 100644 --- a/src/diff_file.c +++ b/src/diff_file.c @@ -304,7 +304,7 @@ static int diff_file_content_load_workdir_symlink( read_len = p_readlink(git_buf_cstr(path), fc->map.data, alloc_len); if (read_len < 0) { - giterr_set(GITERR_OS, "Failed to read symlink '%s'", fc->file->path); + giterr_set(GITERR_OS, "failed to read symlink '%s'", fc->file->path); return -1; } diff --git a/src/diff_generate.c b/src/diff_generate.c index 06f9b19c7..f6cc04fed 100644 --- a/src/diff_generate.c +++ b/src/diff_generate.c @@ -624,7 +624,7 @@ int git_diff__oid_for_entry( error = git_odb__hashlink(out, full_path.ptr); diff->base.perf.oid_calculations++; } else if (!git__is_sizet(entry.file_size)) { - giterr_set(GITERR_OS, "File size overflow (for 32-bits) on '%s'", + giterr_set(GITERR_OS, "file size overflow (for 32-bits) on '%s'", entry.path); error = -1; } else if (!(error = git_filter_list_load(&fl, @@ -1587,7 +1587,7 @@ int git_diff__commit( char commit_oidstr[GIT_OID_HEXSZ + 1]; error = -1; - giterr_set(GITERR_INVALID, "Commit %s is a merge commit", + giterr_set(GITERR_INVALID, "commit %s is a merge commit", git_oid_tostr(commit_oidstr, GIT_OID_HEXSZ + 1, git_commit_id(commit))); goto on_error; } diff --git a/src/diff_print.c b/src/diff_print.c index fd1a186c1..5aa8a37e6 100644 --- a/src/diff_print.c +++ b/src/diff_print.c @@ -222,7 +222,7 @@ static int diff_print_one_raw( if (pi->id_strlen > id_abbrev) { giterr_set(GITERR_PATCH, - "The patch input contains %d id characters (cannot print %d)", + "the patch input contains %d id characters (cannot print %d)", id_abbrev, pi->id_strlen); return -1; } @@ -273,7 +273,7 @@ static int diff_print_oid_range( if (delta->old_file.mode && id_strlen > delta->old_file.id_abbrev) { giterr_set(GITERR_PATCH, - "The patch input contains %d id characters (cannot print %d)", + "the patch input contains %d id characters (cannot print %d)", delta->old_file.id_abbrev, id_strlen); return -1; } @@ -281,7 +281,7 @@ static int diff_print_oid_range( if ((delta->new_file.mode && id_strlen > delta->new_file.id_abbrev)) { giterr_set(GITERR_PATCH, - "The patch input contains %d id characters (cannot print %d)", + "the patch input contains %d id characters (cannot print %d)", delta->new_file.id_abbrev, id_strlen); return -1; } @@ -680,7 +680,7 @@ int git_diff_print( print_file = diff_print_one_name_status; break; default: - giterr_set(GITERR_INVALID, "Unknown diff output format (%d)", format); + giterr_set(GITERR_INVALID, "unknown diff output format (%d)", format); return -1; } @@ -708,7 +708,7 @@ int git_diff_print_callback__to_buf( GIT_UNUSED(delta); GIT_UNUSED(hunk); if (!output) { - giterr_set(GITERR_INVALID, "Buffer pointer must be provided"); + giterr_set(GITERR_INVALID, "buffer pointer must be provided"); return -1; } diff --git a/src/diff_tform.c b/src/diff_tform.c index e8848bd45..f2ff147d1 100644 --- a/src/diff_tform.c +++ b/src/diff_tform.c @@ -131,7 +131,7 @@ int git_diff__merge( if (ignore_case != ((from->opts.flags & GIT_DIFF_IGNORE_CASE) != 0) || reversed != ((from->opts.flags & GIT_DIFF_REVERSE) != 0)) { giterr_set(GITERR_INVALID, - "Attempt to merge diffs created with conflicting options"); + "attempt to merge diffs created with conflicting options"); return -1; } diff --git a/src/diff_xdiff.c b/src/diff_xdiff.c index 5bd6381b5..60c4d85cb 100644 --- a/src/diff_xdiff.c +++ b/src/diff_xdiff.c @@ -50,7 +50,7 @@ static int git_xdiff_parse_hunk(git_diff_hunk *hunk, const char *header) return 0; fail: - giterr_set(GITERR_INVALID, "Malformed hunk header from xdiff"); + giterr_set(GITERR_INVALID, "malformed hunk header from xdiff"); return -1; } @@ -99,7 +99,7 @@ static int diff_update_lines( info->new_lineno += (int)line->num_lines; break; default: - giterr_set(GITERR_INVALID, "Unknown diff line origin %02x", + giterr_set(GITERR_INVALID, "unknown diff line origin %02x", (unsigned int)line->origin); return -1; } diff --git a/src/fetch.c b/src/fetch.c index 4d895752c..f408a5174 100644 --- a/src/fetch.c +++ b/src/fetch.c @@ -113,7 +113,7 @@ int git_fetch_negotiate(git_remote *remote, const git_fetch_options *opts) remote->need_pack = 0; if (filter_wants(remote, opts) < 0) { - giterr_set(GITERR_NET, "Failed to filter the reference list for wants"); + giterr_set(GITERR_NET, "failed to filter the reference list for wants"); return -1; } diff --git a/src/fetchhead.c b/src/fetchhead.c index 3d16c2166..0d9ab2c25 100644 --- a/src/fetchhead.c +++ b/src/fetchhead.c @@ -149,7 +149,7 @@ static int fetchhead_ref_parse( if (!*line) { giterr_set(GITERR_FETCHHEAD, - "Empty line in FETCH_HEAD line %"PRIuZ, line_num); + "empty line in FETCH_HEAD line %"PRIuZ, line_num); return -1; } @@ -163,13 +163,13 @@ static int fetchhead_ref_parse( if (strlen(oid_str) != GIT_OID_HEXSZ) { giterr_set(GITERR_FETCHHEAD, - "Invalid object ID in FETCH_HEAD line %"PRIuZ, line_num); + "invalid object ID in FETCH_HEAD line %"PRIuZ, line_num); return -1; } if (git_oid_fromstr(oid, oid_str) < 0) { const git_error *oid_err = giterr_last(); - const char *err_msg = oid_err ? oid_err->message : "Invalid object ID"; + const char *err_msg = oid_err ? oid_err->message : "invalid object ID"; giterr_set(GITERR_FETCHHEAD, "%s in FETCH_HEAD line %"PRIuZ, err_msg, line_num); @@ -180,7 +180,7 @@ static int fetchhead_ref_parse( if (*line) { if ((is_merge_str = git__strsep(&line, "\t")) == NULL) { giterr_set(GITERR_FETCHHEAD, - "Invalid description data in FETCH_HEAD line %"PRIuZ, line_num); + "invalid description data in FETCH_HEAD line %"PRIuZ, line_num); return -1; } @@ -190,13 +190,13 @@ static int fetchhead_ref_parse( *is_merge = 0; else { giterr_set(GITERR_FETCHHEAD, - "Invalid for-merge entry in FETCH_HEAD line %"PRIuZ, line_num); + "invalid for-merge entry in FETCH_HEAD line %"PRIuZ, line_num); return -1; } if ((desc = line) == NULL) { giterr_set(GITERR_FETCHHEAD, - "Invalid description in FETCH_HEAD line %"PRIuZ, line_num); + "invalid description in FETCH_HEAD line %"PRIuZ, line_num); return -1; } @@ -213,7 +213,7 @@ static int fetchhead_ref_parse( if ((desc = strstr(name, "' ")) == NULL || git__prefixcmp(desc, "' of ") != 0) { giterr_set(GITERR_FETCHHEAD, - "Invalid description in FETCH_HEAD line %"PRIuZ, line_num); + "invalid description in FETCH_HEAD line %"PRIuZ, line_num); return -1; } @@ -277,7 +277,7 @@ int git_repository_fetchhead_foreach(git_repository *repo, } if (*buffer) { - giterr_set(GITERR_FETCHHEAD, "No EOL at line %"PRIuZ, line_num+1); + giterr_set(GITERR_FETCHHEAD, "no EOL at line %"PRIuZ, line_num+1); error = -1; goto done; } diff --git a/src/filebuf.c b/src/filebuf.c index 582399470..ef68b16f4 100644 --- a/src/filebuf.c +++ b/src/filebuf.c @@ -23,7 +23,7 @@ static int verify_last_error(git_filebuf *file) { switch (file->last_error) { case BUFERR_WRITE: - giterr_set(GITERR_OS, "Failed to write out file"); + giterr_set(GITERR_OS, "failed to write out file"); return -1; case BUFERR_MEM: @@ -48,7 +48,7 @@ static int lock_file(git_filebuf *file, int flags, mode_t mode) else { giterr_clear(); /* actual OS error code just confuses */ giterr_set(GITERR_OS, - "Failed to lock file '%s' for writing", file->path_lock); + "failed to lock file '%s' for writing", file->path_lock); return GIT_ELOCKED; } } @@ -75,7 +75,7 @@ static int lock_file(git_filebuf *file, int flags, mode_t mode) source = p_open(file->path_original, O_RDONLY); if (source < 0) { giterr_set(GITERR_OS, - "Failed to open file '%s' for reading", + "failed to open file '%s' for reading", file->path_original); return -1; } @@ -90,10 +90,10 @@ static int lock_file(git_filebuf *file, int flags, mode_t mode) p_close(source); if (read_bytes < 0) { - giterr_set(GITERR_OS, "Failed to read file '%s'", file->path_original); + giterr_set(GITERR_OS, "failed to read file '%s'", file->path_original); return -1; } else if (error < 0) { - giterr_set(GITERR_OS, "Failed to write file '%s'", file->path_lock); + giterr_set(GITERR_OS, "failed to write file '%s'", file->path_lock); return -1; } } @@ -316,7 +316,7 @@ int git_filebuf_open_withsize(git_filebuf *file, const char *path, int flags, mo if (compression != 0) { /* Initialize the ZLib stream */ if (deflateInit(&file->zs, compression) != Z_OK) { - giterr_set(GITERR_ZLIB, "Failed to initialize zlib"); + giterr_set(GITERR_ZLIB, "failed to initialize zlib"); goto cleanup; } @@ -426,14 +426,14 @@ int git_filebuf_commit(git_filebuf *file) file->fd_is_open = false; if (p_close(file->fd) < 0) { - giterr_set(GITERR_OS, "Failed to close file at '%s'", file->path_lock); + giterr_set(GITERR_OS, "failed to close file at '%s'", file->path_lock); goto on_error; } file->fd = -1; if (p_rename(file->path_lock, file->path_original) < 0) { - giterr_set(GITERR_OS, "Failed to rename lockfile to '%s'", file->path_original); + giterr_set(GITERR_OS, "failed to rename lockfile to '%s'", file->path_original); goto on_error; } @@ -571,7 +571,7 @@ int git_filebuf_stats(time_t *mtime, size_t *size, git_filebuf *file) res = p_stat(file->path_original, &st); if (res < 0) { - giterr_set(GITERR_OS, "Could not get stat info for '%s'", + giterr_set(GITERR_OS, "could not get stat info for '%s'", file->path_original); return res; } diff --git a/src/fileops.c b/src/fileops.c index a82202c98..7a8733209 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -37,13 +37,13 @@ int git_futils_mktmp(git_buf *path_out, const char *filename, mode_t mode) if ((fd = p_mkstemp(path_out->ptr)) < 0) { giterr_set(GITERR_OS, - "Failed to create temporary file '%s'", path_out->ptr); + "failed to create temporary file '%s'", path_out->ptr); return -1; } if (p_chmod(path_out->ptr, (mode & ~mask))) { giterr_set(GITERR_OS, - "Failed to set permissions on file '%s'", path_out->ptr); + "failed to set permissions on file '%s'", path_out->ptr); return -1; } @@ -59,7 +59,7 @@ int git_futils_creat_withpath(const char *path, const mode_t dirmode, const mode fd = p_creat(path, mode); if (fd < 0) { - giterr_set(GITERR_OS, "Failed to create file '%s'", path); + giterr_set(GITERR_OS, "failed to create file '%s'", path); return -1; } @@ -73,7 +73,7 @@ int git_futils_creat_locked(const char *path, const mode_t mode) if (fd < 0) { int error = errno; - giterr_set(GITERR_OS, "Failed to create locked file '%s'", path); + giterr_set(GITERR_OS, "failed to create locked file '%s'", path); switch (error) { case EEXIST: return GIT_ELOCKED; @@ -108,7 +108,7 @@ git_off_t git_futils_filesize(git_file fd) struct stat sb; if (p_fstat(fd, &sb)) { - giterr_set(GITERR_OS, "Failed to stat file descriptor"); + giterr_set(GITERR_OS, "failed to stat file descriptor"); return -1; } @@ -137,7 +137,7 @@ int git_futils_readbuffer_fd(git_buf *buf, git_file fd, size_t len) git_buf_clear(buf); if (!git__is_ssizet(len)) { - giterr_set(GITERR_INVALID, "Read too large."); + giterr_set(GITERR_INVALID, "read too large"); return -1; } @@ -149,7 +149,7 @@ int git_futils_readbuffer_fd(git_buf *buf, git_file fd, size_t len) read_size = p_read(fd, buf->ptr, len); if (read_size != (ssize_t)len) { - giterr_set(GITERR_OS, "Failed to read descriptor"); + giterr_set(GITERR_OS, "failed to read descriptor"); git_buf_free(buf); return -1; } @@ -184,7 +184,7 @@ int git_futils_readbuffer_updated( } if (!git__is_sizet(st.st_size+1)) { - giterr_set(GITERR_OS, "Invalid regular file stat for '%s'", path); + giterr_set(GITERR_OS, "invalid regular file stat for '%s'", path); return -1; } @@ -245,18 +245,18 @@ int git_futils_writebuffer( mode = GIT_FILEMODE_BLOB; if ((fd = p_open(path, flags, mode)) < 0) { - giterr_set(GITERR_OS, "Could not open '%s' for writing", path); + giterr_set(GITERR_OS, "could not open '%s' for writing", path); return fd; } if ((error = p_write(fd, git_buf_cstr(buf), git_buf_len(buf))) < 0) { - giterr_set(GITERR_OS, "Could not write to '%s'", path); + giterr_set(GITERR_OS, "could not write to '%s'", path); (void)p_close(fd); return error; } if ((error = p_close(fd)) < 0) - giterr_set(GITERR_OS, "Error while closing '%s'", path); + giterr_set(GITERR_OS, "error while closing '%s'", path); return error; } @@ -267,7 +267,7 @@ int git_futils_mv_withpath(const char *from, const char *to, const mode_t dirmod return -1; if (p_rename(from, to) < 0) { - giterr_set(GITERR_OS, "Failed to rename '%s' to '%s'", from, to); + giterr_set(GITERR_OS, "failed to rename '%s' to '%s'", from, to); return -1; } @@ -290,7 +290,7 @@ int git_futils_mmap_ro_file(git_map *out, const char *path) len = git_futils_filesize(fd); if (!git__is_sizet(len)) { - giterr_set(GITERR_OS, "File `%s` too large to mmap", path); + giterr_set(GITERR_OS, "file `%s` too large to mmap", path); return -1; } @@ -314,14 +314,14 @@ GIT_INLINE(int) mkdir_validate_dir( /* with exclusive create, existing dir is an error */ if ((flags & GIT_MKDIR_EXCL) != 0) { giterr_set(GITERR_FILESYSTEM, - "Failed to make directory '%s': directory exists", path); + "failed to make directory '%s': directory exists", path); return GIT_EEXISTS; } if ((S_ISREG(st->st_mode) && (flags & GIT_MKDIR_REMOVE_FILES)) || (S_ISLNK(st->st_mode) && (flags & GIT_MKDIR_REMOVE_SYMLINKS))) { if (p_unlink(path) < 0) { - giterr_set(GITERR_OS, "Failed to remove %s '%s'", + giterr_set(GITERR_OS, "failed to remove %s '%s'", S_ISLNK(st->st_mode) ? "symlink" : "file", path); return GIT_EEXISTS; } @@ -329,7 +329,7 @@ GIT_INLINE(int) mkdir_validate_dir( opts->perfdata.mkdir_calls++; if (p_mkdir(path, mode) < 0) { - giterr_set(GITERR_OS, "Failed to make directory '%s'", path); + giterr_set(GITERR_OS, "failed to make directory '%s'", path); return GIT_EEXISTS; } } @@ -339,14 +339,14 @@ GIT_INLINE(int) mkdir_validate_dir( opts->perfdata.stat_calls++; if (p_stat(path, st) < 0) { - giterr_set(GITERR_OS, "Failed to make directory '%s'", path); + giterr_set(GITERR_OS, "failed to make directory '%s'", path); return GIT_EEXISTS; } } else if (!S_ISDIR(st->st_mode)) { giterr_set(GITERR_FILESYSTEM, - "Failed to make directory '%s': directory exists", path); + "failed to make directory '%s': directory exists", path); return GIT_EEXISTS; } @@ -569,7 +569,7 @@ int git_futils_mkdir_relative( retry_lstat: if (p_lstat(make_path.ptr, &st) < 0) { if (mkdir_attempted || errno != ENOENT) { - giterr_set(GITERR_OS, "Cannot access component in path '%s'", make_path.ptr); + giterr_set(GITERR_OS, "cannot access component in path '%s'", make_path.ptr); error = -1; goto done; } @@ -580,7 +580,7 @@ retry_lstat: if (p_mkdir(make_path.ptr, mode) < 0) { if (errno == EEXIST) goto retry_lstat; - giterr_set(GITERR_OS, "Failed to make directory '%s'", make_path.ptr); + giterr_set(GITERR_OS, "failed to make directory '%s'", make_path.ptr); error = -1; goto done; } @@ -621,7 +621,7 @@ retry_lstat: opts->perfdata.stat_calls++; if (p_stat(make_path.ptr, &st) < 0 || !S_ISDIR(st.st_mode)) { - giterr_set(GITERR_OS, "Path is not a directory '%s'", + giterr_set(GITERR_OS, "path is not a directory '%s'", make_path.ptr); error = GIT_ENOTFOUND; } @@ -644,10 +644,10 @@ typedef struct { static int futils__error_cannot_rmdir(const char *path, const char *filemsg) { if (filemsg) - giterr_set(GITERR_OS, "Could not remove directory. File '%s' %s", + giterr_set(GITERR_OS, "could not remove directory '%s': %s", path, filemsg); else - giterr_set(GITERR_OS, "Could not remove directory '%s'", path); + giterr_set(GITERR_OS, "could not remove directory '%s'", path); return -1; } @@ -815,7 +815,7 @@ static int cp_by_fd(int ifd, int ofd, bool close_fd_when_done) error = p_write(ofd, buffer, len); if (len < 0) { - giterr_set(GITERR_OS, "Read error while copying file"); + giterr_set(GITERR_OS, "read error while copying file"); error = (int)len; } @@ -871,14 +871,14 @@ static int cp_link(const char *from, const char *to, size_t link_size) read_len = p_readlink(from, link_data, link_size); if (read_len != (ssize_t)link_size) { - giterr_set(GITERR_OS, "Failed to read symlink data for '%s'", from); + giterr_set(GITERR_OS, "failed to read symlink data for '%s'", from); error = -1; } else { link_data[read_len] = '\0'; if (p_symlink(link_data, to) < 0) { - giterr_set(GITERR_OS, "Could not symlink '%s' as '%s'", + giterr_set(GITERR_OS, "could not symlink '%s' as '%s'", link_data, to); error = -1; } @@ -974,7 +974,7 @@ static int _cp_r_callback(void *ref, git_buf *from) return 0; if (p_unlink(info->to.ptr) < 0) { - giterr_set(GITERR_OS, "Cannot overwrite existing file '%s'", + giterr_set(GITERR_OS, "cannot overwrite existing file '%s'", info->to.ptr); return GIT_EEXISTS; } diff --git a/src/filter.c b/src/filter.c index a0628d779..0d8831e0c 100644 --- a/src/filter.c +++ b/src/filter.c @@ -296,7 +296,7 @@ int git_filter_unregister(const char *name) /* cannot unregister default filters */ if (!strcmp(GIT_FILTER_CRLF, name) || !strcmp(GIT_FILTER_IDENT, name)) { - giterr_set(GITERR_FILTER, "Cannot unregister filter '%s'", name); + giterr_set(GITERR_FILTER, "cannot unregister filter '%s'", name); return -1; } @@ -306,7 +306,7 @@ int git_filter_unregister(const char *name) } if ((fdef = filter_registry_lookup(&pos, name)) == NULL) { - giterr_set(GITERR_FILTER, "Cannot find filter '%s' to unregister", name); + giterr_set(GITERR_FILTER, "cannot find filter '%s' to unregister", name); error = GIT_ENOTFOUND; goto done; } @@ -645,7 +645,7 @@ int git_filter_list_push( git_rwlock_rdunlock(&filter_registry.lock); if (fdef == NULL) { - giterr_set(GITERR_FILTER, "Cannot use an unregistered filter"); + giterr_set(GITERR_FILTER, "cannot use an unregistered filter"); return -1; } @@ -758,7 +758,7 @@ static int buf_from_blob(git_buf *out, git_blob *blob) git_off_t rawsize = git_blob_rawsize(blob); if (!git__is_sizet(rawsize)) { - giterr_set(GITERR_OS, "Blob is too large to filter"); + giterr_set(GITERR_OS, "blob is too large to filter"); return -1; } diff --git a/src/hashsig.c b/src/hashsig.c index e99637d8b..bea538349 100644 --- a/src/hashsig.c +++ b/src/hashsig.c @@ -214,7 +214,7 @@ static int hashsig_finalize_hashes(git_hashsig *sig) if (sig->mins.size < HASHSIG_HEAP_MIN_SIZE && !(sig->opt & GIT_HASHSIG_ALLOW_SMALL_FILES)) { giterr_set(GITERR_INVALID, - "File too small for similarity signature calculation"); + "file too small for similarity signature calculation"); return GIT_EBUFS; } @@ -286,7 +286,7 @@ int git_hashsig_create_fromfile( if ((buflen = p_read(fd, buf, sizeof(buf))) <= 0) { if ((error = (int)buflen) < 0) giterr_set(GITERR_OS, - "Read error on '%s' calculating similarity hashes", path); + "read error on '%s' calculating similarity hashes", path); break; } diff --git a/src/ignore.c b/src/ignore.c index dcbd5c1ca..d1a6c5550 100644 --- a/src/ignore.c +++ b/src/ignore.c @@ -175,7 +175,7 @@ static int parse_ignore_file( context = attrs->entry->path; if (git_mutex_lock(&attrs->lock) < 0) { - giterr_set(GITERR_OS, "Failed to lock ignore file"); + giterr_set(GITERR_OS, "failed to lock ignore file"); return -1; } diff --git a/src/index.c b/src/index.c index 42579f19a..f27fa16d2 100644 --- a/src/index.c +++ b/src/index.c @@ -570,7 +570,7 @@ int git_index_set_caps(git_index *index, int caps) if (!repo) return create_index_error( - -1, "Cannot access repository to set index caps"); + -1, "cannot access repository to set index caps"); if (!git_repository__cvar(&val, repo, GIT_CVAR_IGNORECASE)) index->ignore_case = (val != 0); @@ -639,7 +639,7 @@ int git_index_read(git_index *index, int force) if (!index->index_file_path) return create_index_error(-1, - "Failed to read index: The index is in-memory only"); + "failed to read index: The index is in-memory only"); index->on_disk = git_path_exists(index->index_file_path); @@ -653,7 +653,7 @@ int git_index_read(git_index *index, int force) ((updated = compare_checksum(index)) < 0)) { giterr_set( GITERR_INDEX, - "Failed to read index: '%s' no longer exists", + "failed to read index: '%s' no longer exists", index->index_file_path); return updated; } @@ -765,7 +765,7 @@ int git_index_set_version(git_index *index, unsigned int version) if (version < INDEX_VERSION_NUMBER_LB || version > INDEX_VERSION_NUMBER_UB) { - giterr_set(GITERR_INDEX, "Invalid version number"); + giterr_set(GITERR_INDEX, "invalid version number"); return -1; } @@ -805,7 +805,7 @@ int git_index_write_tree(git_oid *oid, git_index *index) if (repo == NULL) return create_index_error(-1, "Failed to write tree. " - "The index file is not backed up by an existing repository"); + "the index file is not backed up by an existing repository"); return git_tree__write_index(oid, index, repo); } @@ -847,7 +847,7 @@ const git_index_entry *git_index_get_bypath( if (git_idxmap_valid_index(index->entries_map, pos)) return git_idxmap_value_at(index->entries_map, pos); - giterr_set(GITERR_INDEX, "Index does not contain %s", path); + giterr_set(GITERR_INDEX, "index does not contain '%s'", path); return NULL; } @@ -934,7 +934,7 @@ static int index_entry_init( if (INDEX_OWNER(index) == NULL) return create_index_error(-1, - "Could not initialize index entry. " + "could not initialize index entry. " "Index is not backed up by an existing repository."); if (index_entry_create(&entry, INDEX_OWNER(index), rel_path, true) < 0) @@ -1423,7 +1423,7 @@ int git_index_add_frombuffer( if (INDEX_OWNER(index) == NULL) return create_index_error(-1, - "Could not initialize index entry. " + "could not initialize index entry. " "Index is not backed up by an existing repository."); if (!valid_filemode(source_entry->mode)) { @@ -1637,7 +1637,7 @@ int git_index_remove(git_index *index, const char *path, int stage) if (index_find(&position, index, path, 0, stage) < 0) { giterr_set( - GITERR_INDEX, "Index does not contain %s at stage %d", path, stage); + GITERR_INDEX, "index does not contain %s at stage %d", path, stage); error = GIT_ENOTFOUND; } else { error = index_remove_entry(index, position); @@ -1709,7 +1709,7 @@ int git_index_find(size_t *at_pos, git_index *index, const char *path) if (git_vector_bsearch2( &pos, &index->entries, index->entries_search_path, path) < 0) { - giterr_set(GITERR_INDEX, "Index does not contain %s", path); + giterr_set(GITERR_INDEX, "index does not contain %s", path); return GIT_ENOTFOUND; } @@ -2153,7 +2153,7 @@ void git_index_reuc_clear(git_index *index) static int index_error_invalid(const char *message) { - giterr_set(GITERR_INDEX, "Invalid data in index - %s", message); + giterr_set(GITERR_INDEX, "invalid data in index - %s", message); return -1; } @@ -3390,7 +3390,7 @@ static int index_apply_to_all( i--; /* back up foreach if we removed this */ break; default: - giterr_set(GITERR_INVALID, "Unknown index action %d", action); + giterr_set(GITERR_INVALID, "unknown index action %d", action); error = -1; break; } @@ -3475,13 +3475,13 @@ int git_indexwriter_init( if (!index->index_file_path) return create_index_error(-1, - "Failed to write index: The index is in-memory only"); + "failed to write index: The index is in-memory only"); if ((error = git_filebuf_open( &writer->file, index->index_file_path, GIT_FILEBUF_HASH_CONTENTS, GIT_INDEX_FILE_MODE)) < 0) { if (error == GIT_ELOCKED) - giterr_set(GITERR_INDEX, "The index is locked. This might be due to a concurrent or crashed process"); + giterr_set(GITERR_INDEX, "the index is locked; this might be due to a concurrent or crashed process"); return error; } @@ -3530,7 +3530,7 @@ int git_indexwriter_commit(git_indexwriter *writer) if ((error = git_futils_filestamp_check( &writer->index->stamp, writer->index->index_file_path)) < 0) { - giterr_set(GITERR_OS, "Could not read index timestamp"); + giterr_set(GITERR_OS, "could not read index timestamp"); return -1; } diff --git a/src/indexer.c b/src/indexer.c index a3a866989..4e8919adb 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -83,12 +83,12 @@ static int parse_header(struct git_pack_header *hdr, struct git_pack_file *pack) /* Verify we recognize this pack file format. */ if (hdr->hdr_signature != ntohl(PACK_SIGNATURE)) { - giterr_set(GITERR_INDEXER, "Wrong pack signature"); + giterr_set(GITERR_INDEXER, "wrong pack signature"); return -1; } if (!pack_version_ok(hdr->hdr_version)) { - giterr_set(GITERR_INDEXER, "Wrong pack version"); + giterr_set(GITERR_INDEXER, "wrong pack version"); return -1; } @@ -376,7 +376,7 @@ static int hash_and_save(git_indexer *idx, git_rawobj *obj, git_off_t entry_star GITERR_CHECK_ALLOC(entry); if (git_odb__hashobj(&oid, obj) < 0) { - giterr_set(GITERR_INDEXER, "Failed to hash object"); + giterr_set(GITERR_INDEXER, "failed to hash object"); goto on_error; } diff --git a/src/merge.c b/src/merge.c index 1142917bd..4d812da50 100644 --- a/src/merge.c +++ b/src/merge.c @@ -78,7 +78,7 @@ int merge_bases_many(git_commit_list **out, git_revwalk **walk_out, git_reposito unsigned int i; if (length < 2) { - giterr_set(GITERR_INVALID, "At least two commits are required to find an ancestor. Provided 'length' was %" PRIuZ ".", length); + giterr_set(GITERR_INVALID, "at least two commits are required to find an ancestor"); return -1; } @@ -104,7 +104,7 @@ int merge_bases_many(git_commit_list **out, git_revwalk **walk_out, git_reposito goto on_error; if (!result) { - giterr_set(GITERR_MERGE, "No merge base found"); + giterr_set(GITERR_MERGE, "no merge base found"); error = GIT_ENOTFOUND; goto on_error; } @@ -184,7 +184,7 @@ int git_merge_base_octopus(git_oid *out, git_repository *repo, size_t length, co assert(out && repo && input_array); if (length < 2) { - giterr_set(GITERR_INVALID, "At least two commits are required to find an ancestor. Provided 'length' was %" PRIuZ ".", length); + giterr_set(GITERR_INVALID, "at least two commits are required to find an ancestor"); return -1; } @@ -230,7 +230,7 @@ static int merge_bases(git_commit_list **out, git_revwalk **walk_out, git_reposi if (!result) { git_revwalk_free(walk); - giterr_set(GITERR_MERGE, "No merge base found"); + giterr_set(GITERR_MERGE, "no merge base found"); return GIT_ENOTFOUND; } @@ -574,7 +574,7 @@ int git_repository_mergehead_foreach( while ((line = git__strsep(&buffer, "\n")) != NULL) { if (strlen(line) != GIT_OID_HEXSZ) { - giterr_set(GITERR_INVALID, "Unable to parse OID - invalid length"); + giterr_set(GITERR_INVALID, "unable to parse OID - invalid length"); error = -1; goto cleanup; } @@ -591,7 +591,7 @@ int git_repository_mergehead_foreach( } if (*buffer) { - giterr_set(GITERR_MERGE, "No EOL at line %"PRIuZ, line_num); + giterr_set(GITERR_MERGE, "no EOL at line %"PRIuZ, line_num); error = -1; goto cleanup; } @@ -3043,7 +3043,7 @@ int git_merge_analysis( assert(analysis_out && preference_out && repo && their_heads); if (their_heads_len != 1) { - giterr_set(GITERR_MERGE, "Can only merge a single branch"); + giterr_set(GITERR_MERGE, "can only merge a single branch"); error = -1; goto done; } @@ -3099,7 +3099,7 @@ int git_merge( assert(repo && their_heads); if (their_heads_len != 1) { - giterr_set(GITERR_MERGE, "Can only merge a single branch"); + giterr_set(GITERR_MERGE, "can only merge a single branch"); return -1; } diff --git a/src/merge_file.c b/src/merge_file.c index 3f14a4f63..5ecd8f4d0 100644 --- a/src/merge_file.c +++ b/src/merge_file.c @@ -127,7 +127,7 @@ static int merge_file__xdiff( if ((xdl_result = xdl_merge(&ancestor_mmfile, &our_mmfile, &their_mmfile, &xmparam, &mmbuffer)) < 0) { - giterr_set(GITERR_MERGE, "Failed to merge files."); + giterr_set(GITERR_MERGE, "failed to merge files"); error = -1; goto done; } diff --git a/src/mwindow.c b/src/mwindow.c index 8a5b5caee..520e7685f 100644 --- a/src/mwindow.c +++ b/src/mwindow.c @@ -231,7 +231,7 @@ static int git_mwindow_close_lru(git_mwindow_file *mwf) } if (!lru_w) { - giterr_set(GITERR_OS, "Failed to close memory window. Couldn't find LRU"); + giterr_set(GITERR_OS, "failed to close memory window; couldn't find LRU"); return -1; } diff --git a/src/netops.c b/src/netops.c index 90326ea59..4b73baa0e 100644 --- a/src/netops.c +++ b/src/netops.c @@ -144,7 +144,7 @@ int gitno_connection_data_from_url( default_port = "80"; if (data->use_ssl) { - giterr_set(GITERR_NET, "Redirect from HTTPS to HTTP is not allowed"); + giterr_set(GITERR_NET, "redirect from HTTPS to HTTP is not allowed"); goto cleanup; } } else if (!git__prefixcmp(url, prefix_https)) { @@ -155,7 +155,7 @@ int gitno_connection_data_from_url( default_port = data->use_ssl ? "443" : "80"; if (!default_port) { - giterr_set(GITERR_NET, "Unrecognized URL prefix"); + giterr_set(GITERR_NET, "unrecognized URL prefix"); goto cleanup; } @@ -187,7 +187,7 @@ int gitno_connection_data_from_url( /* Check for errors in the resulting data */ if (original_host && url[0] != '/' && strcmp(original_host, data->host)) { - giterr_set(GITERR_NET, "Cross host redirect not allowed"); + giterr_set(GITERR_NET, "cross host redirect not allowed"); error = -1; } } @@ -237,7 +237,7 @@ int gitno_extract_url_parts( const char *_host, *_port, *_path, *_userinfo; if (http_parser_parse_url(url, strlen(url), false, &u)) { - giterr_set(GITERR_NET, "Malformed URL '%s'", url); + giterr_set(GITERR_NET, "malformed URL '%s'", url); return GIT_EINVALIDSPEC; } diff --git a/src/notes.c b/src/notes.c index fe8d2164f..75108b9c9 100644 --- a/src/notes.c +++ b/src/notes.c @@ -15,7 +15,7 @@ static int note_error_notfound(void) { - giterr_set(GITERR_INVALID, "Note could not be found"); + giterr_set(GITERR_INVALID, "note could not be found"); return GIT_ENOTFOUND; } @@ -226,7 +226,7 @@ static int remove_note_in_tree_enotfound_cb( GIT_UNUSED(note_oid); GIT_UNUSED(fanout); - giterr_set(GITERR_REPOSITORY, "Object '%s' has no note", annotated_object_sha); + giterr_set(GITERR_REPOSITORY, "object '%s' has no note", annotated_object_sha); return current_error; } @@ -244,7 +244,7 @@ static int insert_note_in_tree_eexists_cb(git_tree **out, GIT_UNUSED(note_oid); GIT_UNUSED(fanout); - giterr_set(GITERR_REPOSITORY, "Note for '%s' exists already", annotated_object_sha); + giterr_set(GITERR_REPOSITORY, "note for '%s' exists already", annotated_object_sha); return current_error; } diff --git a/src/object.c b/src/object.c index 1d45f9f1b..2da36a2ee 100644 --- a/src/object.c +++ b/src/object.c @@ -66,12 +66,12 @@ int git_object__from_odb_object( /* Validate type match */ if (type != GIT_OBJ_ANY && type != odb_obj->cached.type) { giterr_set(GITERR_INVALID, - "The requested type does not match the type in the ODB"); + "the requested type does not match the type in the ODB"); return GIT_ENOTFOUND; } if ((object_size = git_object__size(odb_obj->cached.type)) == 0) { - giterr_set(GITERR_INVALID, "The requested type is invalid"); + giterr_set(GITERR_INVALID, "the requested type is invalid"); return GIT_ENOTFOUND; } @@ -122,7 +122,7 @@ int git_object_lookup_prefix( assert(repo && object_out && id); if (len < GIT_OID_MINPREFIXLEN) { - giterr_set(GITERR_OBJECT, "Ambiguous lookup - OID prefix is too short"); + giterr_set(GITERR_OBJECT, "ambiguous lookup - OID prefix is too short"); return GIT_EAMBIGUOUS; } @@ -147,7 +147,7 @@ int git_object_lookup_prefix( if (type != GIT_OBJ_ANY && type != object->cached.type) { git_object_free(object); giterr_set(GITERR_INVALID, - "The requested type does not match the type in ODB"); + "the requested type does not match the type in ODB"); return GIT_ENOTFOUND; } @@ -292,7 +292,7 @@ static int peel_error(int error, const git_oid *oid, git_otype type) git_oid_fmt(hex_oid, oid); hex_oid[GIT_OID_HEXSZ] = '\0'; - giterr_set(GITERR_OBJECT, "The git_object of id '%s' can not be " + giterr_set(GITERR_OBJECT, "the git_object of id '%s' can not be " "successfully peeled into a %s (git_otype=%i).", hex_oid, type_name, type); return error; diff --git a/src/odb.c b/src/odb.c index 7b194c70f..dc98a6ff7 100644 --- a/src/odb.c +++ b/src/odb.c @@ -176,7 +176,7 @@ int git_odb__hashfd(git_oid *out, git_file fd, size_t size, git_otype type) int error = 0; if (!git_object_typeisloose(type)) { - giterr_set(GITERR_INVALID, "Invalid object type for hash"); + giterr_set(GITERR_INVALID, "invalid object type for hash"); return -1; } @@ -199,7 +199,7 @@ int git_odb__hashfd(git_oid *out, git_file fd, size_t size, git_otype type) * If size is not zero, the file was truncated after we originally * stat'd it, so we consider this a read failure too */ if (read_len < 0 || size > 0) { - giterr_set(GITERR_OS, "Error reading file for hashing"); + giterr_set(GITERR_OS, "error reading file for hashing"); error = -1; goto done; @@ -251,7 +251,7 @@ int git_odb__hashlink(git_oid *out, const char *path) return -1; if (!git__is_int(st.st_size) || (int)st.st_size < 0) { - giterr_set(GITERR_FILESYSTEM, "File size overflow for 32-bit systems"); + giterr_set(GITERR_FILESYSTEM, "file size overflow for 32-bit systems"); return -1; } @@ -269,7 +269,7 @@ int git_odb__hashlink(git_oid *out, const char *path) read_len = p_readlink(path, link_data, size); link_data[size] = '\0'; if (read_len != size) { - giterr_set(GITERR_OS, "Failed to read symlink data for '%s'", path); + giterr_set(GITERR_OS, "failed to read symlink data for '%s'", path); git__free(link_data); return -1; } @@ -295,7 +295,7 @@ int git_odb_hashfile(git_oid *out, const char *path, git_otype type) return fd; if ((size = git_futils_filesize(fd)) < 0 || !git__is_sizet(size)) { - giterr_set(GITERR_OS, "File size overflow for 32-bit systems"); + giterr_set(GITERR_OS, "file size overflow for 32-bit systems"); p_close(fd); return -1; } @@ -475,7 +475,7 @@ size_t git_odb_num_backends(git_odb *odb) static int git_odb__error_unsupported_in_backend(const char *action) { giterr_set(GITERR_ODB, - "Cannot %s - unsupported in the loaded odb backends", action); + "cannot %s - unsupported in the loaded odb backends", action); return -1; } @@ -492,7 +492,7 @@ int git_odb_get_backend(git_odb_backend **out, git_odb *odb, size_t pos) return 0; } - giterr_set(GITERR_ODB, "No ODB backend loaded at index %" PRIuZ, pos); + giterr_set(GITERR_ODB, "no ODB backend loaded at index %" PRIuZ, pos); return GIT_ENOTFOUND; } @@ -517,7 +517,7 @@ static int add_default_backends( if (as_alternates) return 0; - giterr_set(GITERR_ODB, "Failed to load object database in '%s'", objects_dir); + giterr_set(GITERR_ODB, "failed to load object database in '%s'", objects_dir); return -1; } @@ -1264,7 +1264,7 @@ static int git_odb_stream__invalid_length( const char *action) { giterr_set(GITERR_ODB, - "Cannot %s - " + "cannot %s - " "Invalid length. %"PRIuZ" was expected. The " "total size of the received chunks amounts to %"PRIuZ".", action, stream->declared_size, stream->received_bytes); @@ -1399,17 +1399,17 @@ int git_odb__error_notfound( if (oid != NULL) { char oid_str[GIT_OID_HEXSZ + 1]; git_oid_tostr(oid_str, oid_len+1, oid); - giterr_set(GITERR_ODB, "Object not found - %s (%.*s)", + giterr_set(GITERR_ODB, "object not found - %s (%.*s)", message, (int) oid_len, oid_str); } else - giterr_set(GITERR_ODB, "Object not found - %s", message); + giterr_set(GITERR_ODB, "object not found - %s", message); return GIT_ENOTFOUND; } int git_odb__error_ambiguous(const char *message) { - giterr_set(GITERR_ODB, "Ambiguous SHA1 prefix - %s", message); + giterr_set(GITERR_ODB, "ambiguous SHA1 prefix - %s", message); return GIT_EAMBIGUOUS; } diff --git a/src/odb_loose.c b/src/odb_loose.c index f312b9c9c..b2e2f1fb7 100644 --- a/src/odb_loose.c +++ b/src/odb_loose.c @@ -214,7 +214,7 @@ static int finish_inflate(z_stream *s) inflateEnd(s); if ((status != Z_STREAM_END) || (s->avail_in != 0)) { - giterr_set(GITERR_ZLIB, "Failed to finish ZLib inflation. Stream aborted prematurely"); + giterr_set(GITERR_ZLIB, "failed to finish zlib inflation; stream aborted prematurely"); return -1; } @@ -243,7 +243,7 @@ static int inflate_buffer(void *in, size_t inlen, void *out, size_t outlen) zs.avail_in = (uInt)inlen; if (inflateInit(&zs) < Z_OK) { - giterr_set(GITERR_ZLIB, "Failed to inflate buffer"); + giterr_set(GITERR_ZLIB, "failed to inflate buffer"); return -1; } @@ -255,7 +255,7 @@ static int inflate_buffer(void *in, size_t inlen, void *out, size_t outlen) if (status != Z_STREAM_END /* || zs.avail_in != 0 */ || zs.total_out != outlen) { - giterr_set(GITERR_ZLIB, "Failed to inflate buffer. Stream aborted prematurely"); + giterr_set(GITERR_ZLIB, "failed to inflate buffer; stream aborted prematurely"); return -1; } @@ -319,7 +319,7 @@ static int inflate_packlike_loose_disk_obj(git_rawobj *out, git_buf *obj) */ if ((used = get_binary_object_header(&hdr, obj)) == 0 || !git_object_typeisloose(hdr.type)) { - giterr_set(GITERR_ODB, "Failed to inflate loose object."); + giterr_set(GITERR_ODB, "failed to inflate loose object"); return -1; } @@ -366,7 +366,7 @@ static int inflate_disk_obj(git_rawobj *out, git_buf *obj) (used = get_object_header(&hdr, head)) == 0 || !git_object_typeisloose(hdr.type)) { - giterr_set(GITERR_ODB, "Failed to inflate disk object."); + giterr_set(GITERR_ODB, "failed to inflate disk object"); return -1; } @@ -455,7 +455,7 @@ static int read_header_loose(git_rawobj *out, git_buf *loc) || get_object_header(&header_obj, inflated_buffer) == 0 || git_object_typeisloose(header_obj.type) == 0) { - giterr_set(GITERR_ZLIB, "Failed to read loose object header"); + giterr_set(GITERR_ZLIB, "failed to read loose object header"); error = -1; } else { out->len = header_obj.size; diff --git a/src/oid.c b/src/oid.c index 9fe2ebb65..9dc719194 100644 --- a/src/oid.c +++ b/src/oid.c @@ -16,7 +16,7 @@ static char to_hex[] = "0123456789abcdef"; static int oid_error_invalid(const char *msg) { - giterr_set(GITERR_INVALID, "Unable to parse OID - %s", msg); + giterr_set(GITERR_INVALID, "unable to parse OID - %s", msg); return -1; } @@ -380,7 +380,7 @@ int git_oid_shorten_add(git_oid_shorten *os, const char *text_oid) node_index idx; if (os->full) { - giterr_set(GITERR_INVALID, "Unable to shorten OID - OID set full"); + giterr_set(GITERR_INVALID, "unable to shorten OID - OID set full"); return -1; } @@ -395,7 +395,7 @@ int git_oid_shorten_add(git_oid_shorten *os, const char *text_oid) trie_node *node; if (c == -1) { - giterr_set(GITERR_INVALID, "Unable to shorten OID - invalid hex value"); + giterr_set(GITERR_INVALID, "unable to shorten OID - invalid hex value"); return -1; } @@ -410,7 +410,7 @@ int git_oid_shorten_add(git_oid_shorten *os, const char *text_oid) node = push_leaf(os, idx, git__fromhex(tail[0]), &tail[1]); if (node == NULL) { if (os->full) - giterr_set(GITERR_INVALID, "Unable to shorten OID - OID set full"); + giterr_set(GITERR_INVALID, "unable to shorten OID - OID set full"); return -1; } } @@ -418,7 +418,7 @@ int git_oid_shorten_add(git_oid_shorten *os, const char *text_oid) if (node->children[c] == 0) { if (push_leaf(os, idx, c, &text_oid[i + 1]) == NULL) { if (os->full) - giterr_set(GITERR_INVALID, "Unable to shorten OID - OID set full"); + giterr_set(GITERR_INVALID, "unable to shorten OID - OID set full"); return -1; } break; diff --git a/src/openssl_stream.c b/src/openssl_stream.c index ddb9c4ab9..bb9b32c67 100644 --- a/src/openssl_stream.c +++ b/src/openssl_stream.c @@ -257,10 +257,10 @@ static int ssl_set_error(SSL *ssl, int error) switch (err) { case SSL_ERROR_WANT_CONNECT: case SSL_ERROR_WANT_ACCEPT: - giterr_set(GITERR_NET, "SSL error: connection failure\n"); + giterr_set(GITERR_NET, "SSL error: connection failure"); break; case SSL_ERROR_WANT_X509_LOOKUP: - giterr_set(GITERR_NET, "SSL error: x509 error\n"); + giterr_set(GITERR_NET, "SSL error: x509 error"); break; case SSL_ERROR_SYSCALL: e = ERR_get_error(); @@ -327,7 +327,7 @@ static int verify_server_cert(SSL *ssl, const char *host) int i = -1,j; if (SSL_get_verify_result(ssl) != X509_V_OK) { - giterr_set(GITERR_SSL, "The SSL certificate is invalid"); + giterr_set(GITERR_SSL, "the SSL certificate is invalid"); return GIT_ECERTIFICATE; } diff --git a/src/pack-objects.c b/src/pack-objects.c index 9f62322f7..6dbb6cf6c 100644 --- a/src/pack-objects.c +++ b/src/pack-objects.c @@ -162,7 +162,7 @@ int git_packbuilder_new(git_packbuilder **out, git_repository *repo) git_mutex_init(&pb->progress_mutex) || git_cond_init(&pb->progress_cond)) { - giterr_set(GITERR_OS, "Failed to initialize packbuilder mutex"); + giterr_set(GITERR_OS, "failed to initialize packbuilder mutex"); goto on_error; } @@ -225,7 +225,7 @@ int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid, GITERR_CHECK_ALLOC_MULTIPLY(&newsize, newsize, 3 / 2); if (!git__is_uint32(newsize)) { - giterr_set(GITERR_NOMEMORY, "Packfile too large to fit in memory."); + giterr_set(GITERR_NOMEMORY, "packfile too large to fit in memory."); return -1; } @@ -298,7 +298,7 @@ static int get_delta(void **out, git_odb *odb, git_pobject *po) goto on_error; if (error == GIT_EBUFS || delta_size != po->delta_size) { - giterr_set(GITERR_INVALID, "Delta size changed"); + giterr_set(GITERR_INVALID, "delta size changed"); goto on_error; } @@ -808,7 +808,7 @@ static int try_delta(git_packbuilder *pb, struct unpacked *trg, if (sz != trg_size) { giterr_set(GITERR_INVALID, - "Inconsistent target object length"); + "inconsistent target object length"); return -1; } @@ -830,7 +830,7 @@ static int try_delta(git_packbuilder *pb, struct unpacked *trg, if (sz != src_size) { giterr_set(GITERR_INVALID, - "Inconsistent source object length"); + "inconsistent source object length"); return -1; } diff --git a/src/pack.c b/src/pack.c index 2e19b3b62..345ff5259 100644 --- a/src/pack.c +++ b/src/pack.c @@ -45,7 +45,7 @@ static int pack_entry_find_offset( static int packfile_error(const char *message) { - giterr_set(GITERR_ODB, "Invalid pack file - %s", message); + giterr_set(GITERR_ODB, "invalid pack file - %s", message); return -1; } @@ -99,7 +99,7 @@ static int cache_init(git_pack_cache *cache) cache->memory_limit = GIT_PACK_CACHE_MEMORY_LIMIT; if (git_mutex_init(&cache->lock)) { - giterr_set(GITERR_OS, "Failed to initialize pack cache mutex"); + giterr_set(GITERR_OS, "failed to initialize pack cache mutex"); git__free(cache->entries); cache->entries = NULL; @@ -226,7 +226,7 @@ static int pack_index_check(const char *path, struct git_pack_file *p) if (p_fstat(fd, &st) < 0) { p_close(fd); - giterr_set(GITERR_OS, "Unable to stat pack index '%s'", path); + giterr_set(GITERR_OS, "unable to stat pack index '%s'", path); return -1; } @@ -235,7 +235,7 @@ static int pack_index_check(const char *path, struct git_pack_file *p) (idx_size = (size_t)st.st_size) < 4 * 256 + 20 + 20) { p_close(fd); - giterr_set(GITERR_ODB, "Invalid pack index '%s'", path); + giterr_set(GITERR_ODB, "invalid pack index '%s'", path); return -1; } @@ -1082,7 +1082,7 @@ static int packfile_open(struct git_pack_file *p) return 0; cleanup: - giterr_set(GITERR_OS, "Invalid packfile '%s'", p->pack_name); + giterr_set(GITERR_OS, "invalid packfile '%s'", p->pack_name); if (p->mwf.fd >= 0) p_close(p->mwf.fd); @@ -1158,7 +1158,7 @@ int git_packfile_alloc(struct git_pack_file **pack_out, const char *path) p->index_version = -1; if (git_mutex_init(&p->lock)) { - giterr_set(GITERR_OS, "Failed to initialize packfile mutex"); + giterr_set(GITERR_OS, "failed to initialize packfile mutex"); git__free(p); return -1; } diff --git a/src/patch_generate.c b/src/patch_generate.c index 0e5d1db31..3559cc2b8 100644 --- a/src/patch_generate.c +++ b/src/patch_generate.c @@ -417,7 +417,7 @@ static int diff_required(git_diff *diff, const char *action) { if (diff) return 0; - giterr_set(GITERR_INVALID, "Must provide valid diff to %s", action); + giterr_set(GITERR_INVALID, "must provide valid diff to %s", action); return -1; } @@ -776,7 +776,7 @@ int git_patch_generated_from_diff( delta = git_vector_get(&diff->deltas, idx); if (!delta) { - giterr_set(GITERR_INVALID, "Index out of range for delta in diff"); + giterr_set(GITERR_INVALID, "index out of range for delta in diff"); return GIT_ENOTFOUND; } diff --git a/src/path.c b/src/path.c index 767552778..bffde930b 100644 --- a/src/path.c +++ b/src/path.c @@ -341,7 +341,7 @@ int git_path_prettify(git_buf *path_out, const char *path, const char *base) if (p_realpath(path, buf) == NULL) { /* giterr_set resets the errno when dealing with a GITERR_OS kind of error */ int error = (errno == ENOENT || errno == ENOTDIR) ? GIT_ENOTFOUND : -1; - giterr_set(GITERR_OS, "Failed to resolve path '%s'", path); + giterr_set(GITERR_OS, "failed to resolve path '%s'", path); git_buf_clear(path_out); @@ -632,24 +632,24 @@ int git_path_set_error(int errno_value, const char *path, const char *action) switch (errno_value) { case ENOENT: case ENOTDIR: - giterr_set(GITERR_OS, "Could not find '%s' to %s", path, action); + giterr_set(GITERR_OS, "could not find '%s' to %s", path, action); return GIT_ENOTFOUND; case EINVAL: case ENAMETOOLONG: - giterr_set(GITERR_OS, "Invalid path for filesystem '%s'", path); + giterr_set(GITERR_OS, "invalid path for filesystem '%s'", path); return GIT_EINVALIDSPEC; case EEXIST: - giterr_set(GITERR_OS, "Failed %s - '%s' already exists", action, path); + giterr_set(GITERR_OS, "failed %s - '%s' already exists", action, path); return GIT_EEXISTS; case EACCES: - giterr_set(GITERR_OS, "Failed %s - '%s' is locked", action, path); + giterr_set(GITERR_OS, "failed %s - '%s' is locked", action, path); return GIT_ELOCKED; default: - giterr_set(GITERR_OS, "Could not %s '%s'", action, path); + giterr_set(GITERR_OS, "could not %s '%s'", action, path); return -1; } } @@ -758,7 +758,7 @@ int git_path_resolve_relative(git_buf *path, size_t ceiling) /* error out if trying to up one from a hard base */ if (to == base && ceiling != 0) { giterr_set(GITERR_INVALID, - "Cannot strip root component off url"); + "cannot strip root component off url"); return -1; } @@ -987,7 +987,7 @@ int git_path_iconv(git_path_iconv_t *ic, const char **in, size_t *inlen) return 0; fail: - giterr_set(GITERR_OS, "Unable to convert unicode path data"); + giterr_set(GITERR_OS, "unable to convert unicode path data"); return -1; } @@ -1080,7 +1080,7 @@ int git_path_direach( wd_len = git_buf_len(path); if ((dir = opendir(path->ptr)) == NULL) { - giterr_set(GITERR_OS, "Failed to open directory '%s'", path->ptr); + giterr_set(GITERR_OS, "failed to open directory '%s'", path->ptr); if (errno == ENOENT) return GIT_ENOTFOUND; @@ -1161,13 +1161,13 @@ int git_path_diriter_init( git_path_trim_slashes(&diriter->path_utf8); if (diriter->path_utf8.size == 0) { - giterr_set(GITERR_FILESYSTEM, "Could not open directory '%s'", path); + giterr_set(GITERR_FILESYSTEM, "could not open directory '%s'", path); return -1; } if ((diriter->parent_len = git_win32_path_from_utf8(diriter->path, diriter->path_utf8.ptr)) < 0 || !git_win32__findfirstfile_filter(path_filter, diriter->path_utf8.ptr)) { - giterr_set(GITERR_OS, "Could not parse the directory path '%s'", path); + giterr_set(GITERR_OS, "could not parse the directory path '%s'", path); return -1; } @@ -1180,7 +1180,7 @@ int git_path_diriter_init( is_win7_or_later ? FIND_FIRST_EX_LARGE_FETCH : 0); if (diriter->handle == INVALID_HANDLE_VALUE) { - giterr_set(GITERR_OS, "Could not open directory '%s'", path); + giterr_set(GITERR_OS, "could not open directory '%s'", path); return -1; } @@ -1310,14 +1310,14 @@ int git_path_diriter_init( git_path_trim_slashes(&diriter->path); if (diriter->path.size == 0) { - giterr_set(GITERR_FILESYSTEM, "Could not open directory '%s'", path); + giterr_set(GITERR_FILESYSTEM, "could not open directory '%s'", path); return -1; } if ((diriter->dir = opendir(diriter->path.ptr)) == NULL) { git_buf_free(&diriter->path); - giterr_set(GITERR_OS, "Failed to open directory '%s'", path); + giterr_set(GITERR_OS, "failed to open directory '%s'", path); return -1; } @@ -1350,7 +1350,7 @@ int git_path_diriter_next(git_path_diriter *diriter) return GIT_ITEROVER; giterr_set(GITERR_OS, - "Could not read directory '%s'", diriter->path.ptr); + "could not read directory '%s'", diriter->path.ptr); return -1; } } while (skip_dot && git_path_is_dot_or_dotdot(de->d_name)); diff --git a/src/pathspec.c b/src/pathspec.c index 361b398b8..00dba4f6b 100644 --- a/src/pathspec.c +++ b/src/pathspec.c @@ -487,7 +487,7 @@ static int pathspec_match_from_iterator( /* if every pattern failed to match, then we have failed */ if ((flags & GIT_PATHSPEC_NO_MATCH_ERROR) != 0 && !found_files) { - giterr_set(GITERR_INVALID, "No matching files were found"); + giterr_set(GITERR_INVALID, "no matching files were found"); error = GIT_ENOTFOUND; } @@ -658,7 +658,7 @@ int git_pathspec_match_diff( /* if every pattern failed to match, then we have failed */ if ((flags & GIT_PATHSPEC_NO_MATCH_ERROR) != 0 && !found_deltas) { - giterr_set(GITERR_INVALID, "No matching deltas were found"); + giterr_set(GITERR_INVALID, "no matching deltas were found"); error = GIT_ENOTFOUND; } diff --git a/src/posix.c b/src/posix.c index b3f1a1cd3..e68f324f6 100644 --- a/src/posix.c +++ b/src/posix.c @@ -240,7 +240,7 @@ int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offs out->len = 0; if ((prot & GIT_PROT_WRITE) && ((flags & GIT_MAP_TYPE) == GIT_MAP_SHARED)) { - giterr_set(GITERR_OS, "Trying to map shared-writeable"); + giterr_set(GITERR_OS, "trying to map shared-writeable"); return -1; } diff --git a/src/push.c b/src/push.c index b4901388b..09c234034 100644 --- a/src/push.c +++ b/src/push.c @@ -90,7 +90,7 @@ static void free_refspec(push_spec *spec) static int check_rref(char *ref) { if (git__prefixcmp(ref, "refs/")) { - giterr_set(GITERR_INVALID, "Not a valid reference '%s'", ref); + giterr_set(GITERR_INVALID, "not a valid reference '%s'", ref); return -1; } @@ -111,7 +111,7 @@ static int check_lref(git_push *push, char *ref) giterr_set(GITERR_REFERENCE, "src refspec '%s' does not match any existing object", ref); else - giterr_set(GITERR_INVALID, "Not a valid reference '%s'", ref); + giterr_set(GITERR_INVALID, "not a valid reference '%s'", ref); return -1; } @@ -321,7 +321,7 @@ static int revwalk(git_vector *commits, git_push *push) if (!git_odb_exists(push->repo->_odb, &spec->roid)) { giterr_set(GITERR_REFERENCE, - "Cannot push because a reference that you are trying to update on the remote contains commits that are not present locally."); + "cannot push because a reference that you are trying to update on the remote contains commits that are not present locally."); error = GIT_ENONFASTFORWARD; goto on_error; } @@ -332,7 +332,7 @@ static int revwalk(git_vector *commits, git_push *push) if (error == GIT_ENOTFOUND || (!error && !git_oid_equal(&base, &spec->roid))) { giterr_set(GITERR_REFERENCE, - "Cannot push non-fastforwardable reference"); + "cannot push non-fastforwardable reference"); error = GIT_ENONFASTFORWARD; goto on_error; } @@ -553,7 +553,7 @@ static int calculate_work(git_push *push) /* This is a create or update. Local ref must exist. */ if (git_reference_name_to_id( &spec->loid, push->repo, spec->refspec.src) < 0) { - giterr_set(GITERR_REFERENCE, "No such reference '%s'", spec->refspec.src); + giterr_set(GITERR_REFERENCE, "no such reference '%s'", spec->refspec.src); return -1; } } @@ -579,7 +579,7 @@ static int do_push(git_push *push, const git_remote_callbacks *callbacks) git_transport *transport = push->remote->transport; if (!transport->push) { - giterr_set(GITERR_NET, "Remote transport doesn't support push"); + giterr_set(GITERR_NET, "remote transport doesn't support push"); error = -1; goto on_error; } diff --git a/src/rebase.c b/src/rebase.c index ef044692a..b2024a439 100644 --- a/src/rebase.c +++ b/src/rebase.c @@ -152,7 +152,7 @@ GIT_INLINE(int) rebase_readint( return error; if (git__strtol32(&num, asc_out->ptr, &eol, 10) < 0 || num < 0 || *eol) { - giterr_set(GITERR_REBASE, "The file '%s' contains an invalid numeric value", filename); + giterr_set(GITERR_REBASE, "the file '%s' contains an invalid numeric value", filename); return -1; } @@ -170,7 +170,7 @@ GIT_INLINE(int) rebase_readoid( return error; if (str_out->size != GIT_OID_HEXSZ || git_oid_fromstr(out, str_out->ptr) < 0) { - giterr_set(GITERR_REBASE, "The file '%s' contains an invalid object ID", filename); + giterr_set(GITERR_REBASE, "the file '%s' contains an invalid object ID", filename); return -1; } @@ -316,7 +316,7 @@ int git_rebase_open( goto done; if (rebase->type == GIT_REBASE_TYPE_NONE) { - giterr_set(GITERR_REBASE, "There is no rebase in progress"); + giterr_set(GITERR_REBASE, "there is no rebase in progress"); error = GIT_ENOTFOUND; goto done; } @@ -372,14 +372,14 @@ int git_rebase_open( switch (rebase->type) { case GIT_REBASE_TYPE_INTERACTIVE: - giterr_set(GITERR_REBASE, "Interactive rebase is not supported"); + giterr_set(GITERR_REBASE, "interactive rebase is not supported"); error = -1; break; case GIT_REBASE_TYPE_MERGE: error = rebase_open_merge(rebase); break; case GIT_REBASE_TYPE_APPLY: - giterr_set(GITERR_REBASE, "Patch application rebase is not supported"); + giterr_set(GITERR_REBASE, "patch application rebase is not supported"); error = -1; break; default: @@ -478,7 +478,7 @@ static int rebase_setupfiles(git_rebase *rebase) git_oid_fmt(orig_head, &rebase->orig_head_id); if (p_mkdir(rebase->state_path, REBASE_DIR_MODE) < 0) { - giterr_set(GITERR_OS, "Failed to create rebase directory '%s'", rebase->state_path); + giterr_set(GITERR_OS, "failed to create rebase directory '%s'", rebase->state_path); return -1; } @@ -511,7 +511,7 @@ static int rebase_ensure_not_in_progress(git_repository *repo) return error; if (type != GIT_REBASE_TYPE_NONE) { - giterr_set(GITERR_REBASE, "There is an existing rebase in progress"); + giterr_set(GITERR_REBASE, "there is an existing rebase in progress"); return -1; } @@ -536,7 +536,7 @@ static int rebase_ensure_not_dirty( goto done; if (git_diff_num_deltas(diff) > 0) { - giterr_set(GITERR_REBASE, "Uncommitted changes exist in index"); + giterr_set(GITERR_REBASE, "uncommitted changes exist in index"); error = fail_with; goto done; } @@ -550,7 +550,7 @@ static int rebase_ensure_not_dirty( goto done; if (git_diff_num_deltas(diff) > 0) { - giterr_set(GITERR_REBASE, "Unstaged changes exist in workdir"); + giterr_set(GITERR_REBASE, "unstaged changes exist in workdir"); error = fail_with; goto done; } @@ -807,7 +807,7 @@ static int rebase_next_merge( goto done; if ((parent_count = git_commit_parentcount(current_commit)) > 1) { - giterr_set(GITERR_REBASE, "Cannot rebase a merge commit"); + giterr_set(GITERR_REBASE, "cannot rebase a merge commit"); error = -1; goto done; } else if (parent_count) { @@ -864,7 +864,7 @@ static int rebase_next_inmemory( goto done; if ((parent_count = git_commit_parentcount(current_commit)) > 1) { - giterr_set(GITERR_REBASE, "Cannot rebase a merge commit"); + giterr_set(GITERR_REBASE, "cannot rebase a merge commit"); error = -1; goto done; } else if (parent_count) { @@ -1259,7 +1259,7 @@ static int rebase_copy_notes( goto done; on_error: - giterr_set(GITERR_REBASE, "Invalid rewritten file at line %d", linenum); + giterr_set(GITERR_REBASE, "invalid rewritten file at line %d", linenum); error = -1; done: diff --git a/src/refdb.c b/src/refdb.c index 85c84892b..1ee0efb31 100644 --- a/src/refdb.c +++ b/src/refdb.c @@ -128,7 +128,7 @@ int git_refdb_iterator(git_reference_iterator **out, git_refdb *db, const char * int error; if (!db->backend || !db->backend->iterator) { - giterr_set(GITERR_REFERENCE, "This backend doesn't support iterators"); + giterr_set(GITERR_REFERENCE, "this backend doesn't support iterators"); return -1; } diff --git a/src/refdb_fs.c b/src/refdb_fs.c index 8739d5b89..e40f48bd5 100644 --- a/src/refdb_fs.c +++ b/src/refdb_fs.c @@ -185,7 +185,7 @@ static int packed_reload(refdb_fs_backend *backend) return 0; parse_failed: - giterr_set(GITERR_REFERENCE, "Corrupted packed references file"); + giterr_set(GITERR_REFERENCE, "corrupted packed references file"); git_sortedcache_clear(backend->refcache, false); git_sortedcache_wunlock(backend->refcache); @@ -212,7 +212,7 @@ static int loose_parse_oid( return 0; corrupted: - giterr_set(GITERR_REFERENCE, "Corrupted loose reference file: %s", filename); + giterr_set(GITERR_REFERENCE, "corrupted loose reference file: %s", filename); return -1; } @@ -349,7 +349,7 @@ static const char *loose_parse_symbolic(git_buf *file_content) refname_start = (const char *)file_content->ptr; if (git_buf_len(file_content) < header_len + 1) { - giterr_set(GITERR_REFERENCE, "Corrupted loose reference file"); + giterr_set(GITERR_REFERENCE, "corrupted loose reference file"); return NULL; } @@ -398,7 +398,7 @@ static int loose_lookup( static int ref_error_notfound(const char *name) { - giterr_set(GITERR_REFERENCE, "Reference '%s' not found", name); + giterr_set(GITERR_REFERENCE, "reference '%s' not found", name); return GIT_ENOTFOUND; } @@ -691,7 +691,7 @@ static int reference_path_available( if (exists) { giterr_set(GITERR_REFERENCE, - "Failed to write reference '%s': a reference with " + "failed to write reference '%s': a reference with " "that name already exists.", new_ref); return GIT_EEXISTS; } @@ -705,7 +705,7 @@ static int reference_path_available( if (ref && !ref_is_available(old_ref, new_ref, ref->name)) { git_sortedcache_runlock(backend->refcache); giterr_set(GITERR_REFERENCE, - "Path to reference '%s' collides with existing one", new_ref); + "path to reference '%s' collides with existing one", new_ref); return -1; } } @@ -722,7 +722,7 @@ static int loose_lock(git_filebuf *file, refdb_fs_backend *backend, const char * assert(file && backend && name); if (!git_path_isvalid(backend->repo, name, GIT_PATH_REJECT_FILESYSTEM_DEFAULTS)) { - giterr_set(GITERR_INVALID, "Invalid reference name '%s'.", name); + giterr_set(GITERR_INVALID, "invalid reference name '%s'", name); return GIT_EINVALIDSPEC; } @@ -1484,7 +1484,7 @@ static int reflog_parse(git_reflog *log, const char *buf, size_t buf_size) #define seek_forward(_increase) do { \ if (_increase >= buf_size) { \ - giterr_set(GITERR_INVALID, "Ran out of data while parsing reflog"); \ + giterr_set(GITERR_INVALID, "ran out of data while parsing reflog"); \ goto fail; \ } \ buf += _increase; \ @@ -1700,7 +1700,7 @@ static int lock_reflog(git_filebuf *file, refdb_fs_backend *backend, const char repo = backend->repo; if (!git_path_isvalid(backend->repo, refname, GIT_PATH_REJECT_FILESYSTEM_DEFAULTS)) { - giterr_set(GITERR_INVALID, "Invalid reference name '%s'.", refname); + giterr_set(GITERR_INVALID, "invalid reference name '%s'", refname); return GIT_EINVALIDSPEC; } @@ -1709,7 +1709,7 @@ static int lock_reflog(git_filebuf *file, refdb_fs_backend *backend, const char if (!git_path_isfile(git_buf_cstr(&log_path))) { giterr_set(GITERR_INVALID, - "Log file for reference '%s' doesn't exist.", refname); + "log file for reference '%s' doesn't exist", refname); error = -1; goto cleanup; } @@ -1889,7 +1889,7 @@ static int refdb_reflog_fs__rename(git_refdb_backend *_backend, const char *old_ p_close(fd); if (p_rename(git_buf_cstr(&old_path), git_buf_cstr(&temp_path)) < 0) { - giterr_set(GITERR_OS, "Failed to rename reflog for %s", new_name); + giterr_set(GITERR_OS, "failed to rename reflog for %s", new_name); error = -1; goto cleanup; } @@ -1906,7 +1906,7 @@ static int refdb_reflog_fs__rename(git_refdb_backend *_backend, const char *old_ } if (p_rename(git_buf_cstr(&temp_path), git_buf_cstr(&new_path)) < 0) { - giterr_set(GITERR_OS, "Failed to rename reflog for %s", new_name); + giterr_set(GITERR_OS, "failed to rename reflog for %s", new_name); error = -1; } diff --git a/src/reflog.c b/src/reflog.c index 9ce9aee6f..98ef1b669 100644 --- a/src/reflog.c +++ b/src/reflog.c @@ -93,7 +93,7 @@ int git_reflog_append(git_reflog *reflog, const git_oid *new_oid, const git_sign if (newline) { if (newline[1] != '\0') { - giterr_set(GITERR_INVALID, "Reflog message cannot contain newline"); + giterr_set(GITERR_INVALID, "reflog message cannot contain newline"); goto cleanup; } @@ -193,7 +193,7 @@ int git_reflog_drop(git_reflog *reflog, size_t idx, int rewrite_previous_entry) entry = (git_reflog_entry *)git_reflog_entry_byindex(reflog, idx); if (entry == NULL) { - giterr_set(GITERR_REFERENCE, "No reflog entry at index %"PRIuZ, idx); + giterr_set(GITERR_REFERENCE, "no reflog entry at index %"PRIuZ, idx); return GIT_ENOTFOUND; } diff --git a/src/refs.c b/src/refs.c index bff443ac9..dbc7e5e8e 100644 --- a/src/refs.c +++ b/src/refs.c @@ -236,7 +236,7 @@ int git_reference_lookup_resolved( if (scan_type != GIT_REF_OID && max_nesting != 0) { giterr_set(GITERR_REFERENCE, - "Cannot resolve reference (>%u levels deep)", max_nesting); + "cannot resolve reference (>%u levels deep)", max_nesting); git_reference_free(ref); return -1; } @@ -298,7 +298,7 @@ cleanup: if (error && !foundvalid) { /* never found a valid reference name */ giterr_set(GITERR_REFERENCE, - "Could not use '%s' as valid reference name", git_buf_cstr(&name)); + "could not use '%s' as valid reference name", git_buf_cstr(&name)); } if (error == GIT_ENOTFOUND) @@ -396,7 +396,7 @@ static int reference__create( if (!git_object__is_valid(repo, oid, GIT_OBJ_ANY)) { giterr_set(GITERR_REFERENCE, - "Target OID for the reference doesn't exist on the repository"); + "target OID for the reference doesn't exist on the repository"); return -1; } @@ -524,7 +524,7 @@ static int ensure_is_an_updatable_direct_reference(git_reference *ref) if (ref->type == GIT_REF_OID) return 0; - giterr_set(GITERR_REFERENCE, "Cannot set OID on symbolic reference"); + giterr_set(GITERR_REFERENCE, "cannot set OID on symbolic reference"); return -1; } @@ -552,7 +552,7 @@ static int ensure_is_an_updatable_symbolic_reference(git_reference *ref) if (ref->type == GIT_REF_SYMBOLIC) return 0; - giterr_set(GITERR_REFERENCE, "Cannot set symbolic target on a direct reference"); + giterr_set(GITERR_REFERENCE, "cannot set symbolic target on a direct reference"); return -1; } @@ -599,7 +599,7 @@ static int reference__rename(git_reference **out, git_reference *ref, const char /* Update HEAD it was pointing to the reference being renamed */ if (should_head_be_updated && (error = git_repository_set_head(ref->db->repo, normalized)) < 0) { - giterr_set(GITERR_REFERENCE, "Failed to update HEAD after renaming reference"); + giterr_set(GITERR_REFERENCE, "failed to update HEAD after renaming reference"); return error; } @@ -636,7 +636,7 @@ int git_reference_resolve(git_reference **ref_out, const git_reference *ref) return git_reference_lookup_resolved(ref_out, ref->db->repo, ref->target.symbolic, -1); default: - giterr_set(GITERR_REFERENCE, "Invalid reference"); + giterr_set(GITERR_REFERENCE, "invalid reference"); return -1; } } @@ -973,7 +973,7 @@ cleanup: if (error == GIT_EINVALIDSPEC) giterr_set( GITERR_REFERENCE, - "The given reference name '%s' is not valid", name); + "the given reference name '%s' is not valid", name); if (error && normalize) git_buf_free(buf); @@ -1000,7 +1000,7 @@ int git_reference_normalize_name( if (git_buf_len(&buf) > buffer_size - 1) { giterr_set( GITERR_REFERENCE, - "The provided buffer is too short to hold the normalization of '%s'", name); + "the provided buffer is too short to hold the normalization of '%s'", name); error = GIT_EBUFS; goto cleanup; } @@ -1046,7 +1046,7 @@ static int get_terminal(git_reference **out, git_repository *repo, const char *r int error = 0; if (nesting > MAX_NESTING_LEVEL) { - giterr_set(GITERR_REFERENCE, "Reference chain too deep (%d)", nesting); + giterr_set(GITERR_REFERENCE, "reference chain too deep (%d)", nesting); return GIT_ENOTFOUND; } @@ -1229,7 +1229,7 @@ static int peel_error(int error, git_reference *ref, const char* msg) { giterr_set( GITERR_INVALID, - "The reference '%s' cannot be peeled - %s", git_reference_name(ref), msg); + "the reference '%s' cannot be peeled - %s", git_reference_name(ref), msg); return error; } diff --git a/src/remote.c b/src/remote.c index c1d7d59ea..8da7346fb 100644 --- a/src/remote.c +++ b/src/remote.c @@ -283,7 +283,7 @@ static int ensure_remote_doesnot_exist(git_repository *repo, const char *name) giterr_set( GITERR_CONFIG, - "Remote '%s' already exists.", name); + "remote '%s' already exists", name); return GIT_EEXISTS; } @@ -476,7 +476,7 @@ int git_remote_lookup(git_remote **out, git_repository *repo, const char *name) if (!optional_setting_found) { error = GIT_ENOTFOUND; - giterr_set(GITERR_CONFIG, "Remote '%s' does not exist.", name); + giterr_set(GITERR_CONFIG, "remote '%s' does not exist", name); goto cleanup; } @@ -1718,7 +1718,7 @@ int git_remote_set_autotag(git_repository *repo, const char *remote, git_remote_ error = 0; break; default: - giterr_set(GITERR_INVALID, "Invalid value for the tagopt setting"); + giterr_set(GITERR_INVALID, "invalid value for the tagopt setting"); error = -1; } diff --git a/src/repository.c b/src/repository.c index 5c4442360..60299193f 100644 --- a/src/repository.c +++ b/src/repository.c @@ -332,7 +332,7 @@ static int read_gitfile(git_buf *path_out, const char *file_path) memcmp(git_buf_cstr(&file), GIT_FILE_CONTENT_PREFIX, prefix_len) != 0) { giterr_set(GITERR_REPOSITORY, - "The `.git` file at '%s' is malformed", file_path); + "the `.git` file at '%s' is malformed", file_path); error = -1; } else if ((error = git_path_dirname_r(path_out, file_path)) >= 0) { @@ -459,7 +459,7 @@ static int find_repo( * to report, report that. */ if (!git_buf_len(repo_path) && !error) { giterr_set(GITERR_REPOSITORY, - "Could not find repository from '%s'", start_path); + "could not find repository from '%s'", start_path); error = GIT_ENOTFOUND; } @@ -481,7 +481,7 @@ int git_repository_open_bare( if (!valid_repository_path(&path)) { git_buf_free(&path); - giterr_set(GITERR_REPOSITORY, "Path is not a repository: %s", bare_path); + giterr_set(GITERR_REPOSITORY, "path is not a repository: %s", bare_path); return GIT_ENOTFOUND; } @@ -1180,7 +1180,7 @@ static int check_repositoryformatversion(git_config *config) if (GIT_REPO_VERSION < version) { giterr_set(GITERR_REPOSITORY, - "Unsupported repository version %d. Only versions up to %d are supported.", + "unsupported repository version %d. Only versions up to %d are supported.", version, GIT_REPO_VERSION); return -1; } @@ -1274,12 +1274,12 @@ static int create_empty_file(const char *path, mode_t mode) int fd; if ((fd = p_creat(path, mode)) < 0) { - giterr_set(GITERR_OS, "Error while creating '%s'", path); + giterr_set(GITERR_OS, "error while creating '%s'", path); return -1; } if (p_close(fd) < 0) { - giterr_set(GITERR_OS, "Error while closing '%s'", path); + giterr_set(GITERR_OS, "error while closing '%s'", path); return -1; } @@ -1508,7 +1508,7 @@ static int repo_write_template( if (error) giterr_set(GITERR_OS, - "Failed to initialize repository with template '%s'", file); + "failed to initialize repository with template '%s'", file); return error; } @@ -1539,7 +1539,7 @@ static int repo_write_gitlink( if (!p_stat(buf.ptr, &st) && !S_ISREG(st.st_mode)) { giterr_set(GITERR_REPOSITORY, - "Cannot overwrite gitlink file into path '%s'", in_dir); + "cannot overwrite gitlink file into path '%s'", in_dir); error = GIT_EEXISTS; goto cleanup; } @@ -1593,7 +1593,7 @@ static int repo_init_structure( if ((opts->flags & GIT_REPOSITORY_INIT__HAS_DOTGIT) != 0) { if (git_win32__set_hidden(repo_dir, true) < 0) { giterr_set(GITERR_OS, - "Failed to mark Git repository folder as hidden"); + "failed to mark Git repository folder as hidden"); return -1; } } @@ -1747,7 +1747,7 @@ static int repo_init_directories( if (git_path_dirname_r(wd_path, repo_path->ptr) < 0) return -1; } else { - giterr_set(GITERR_REPOSITORY, "Cannot pick working directory" + giterr_set(GITERR_REPOSITORY, "cannot pick working directory" " for non-bare repository that isn't a '.git' directory"); return -1; } @@ -1867,7 +1867,7 @@ int git_repository_init_ext( if ((opts->flags & GIT_REPOSITORY_INIT_NO_REINIT) != 0) { giterr_set(GITERR_REPOSITORY, - "Attempt to reinitialize '%s'", given_repo); + "attempt to reinitialize '%s'", given_repo); error = GIT_EEXISTS; goto cleanup; } @@ -2149,7 +2149,7 @@ int git_repository_message(git_buf *out, git_repository *repo) if ((error = p_stat(git_buf_cstr(&path), &st)) < 0) { if (errno == ENOENT) error = GIT_ENOTFOUND; - giterr_set(GITERR_OS, "Could not access message file"); + giterr_set(GITERR_OS, "could not access message file"); } else { error = git_futils_readbuffer(out, git_buf_cstr(&path)); } @@ -2227,7 +2227,7 @@ int git_repository_hashfile( } if (!git__is_sizet(len)) { - giterr_set(GITERR_OS, "File size overflow for 32-bit systems"); + giterr_set(GITERR_OS, "file size overflow for 32-bit systems"); error = -1; goto cleanup; } diff --git a/src/repository.h b/src/repository.h index fd679b483..b259bea3b 100644 --- a/src/repository.h +++ b/src/repository.h @@ -182,7 +182,7 @@ GIT_INLINE(int) git_repository__ensure_not_bare( giterr_set( GITERR_REPOSITORY, - "Cannot %s. This operation is not allowed against bare repositories.", + "cannot %s. This operation is not allowed against bare repositories.", operation_name); return GIT_EBAREREPO; diff --git a/src/reset.c b/src/reset.c index db0bfb373..066b5dbda 100644 --- a/src/reset.c +++ b/src/reset.c @@ -137,7 +137,7 @@ static int reset( (git_repository_state(repo) == GIT_REPOSITORY_STATE_MERGE || git_index_has_conflicts(index))) { - giterr_set(GITERR_OBJECT, "%s (soft) in the middle of a merge.", ERROR_MSG); + giterr_set(GITERR_OBJECT, "%s (soft) in the middle of a merge", ERROR_MSG); error = GIT_EUNMERGED; goto cleanup; } diff --git a/src/revert.c b/src/revert.c index c481e7dea..b255245bf 100644 --- a/src/revert.c +++ b/src/revert.c @@ -133,13 +133,13 @@ int git_revert_commit( if (git_commit_parentcount(revert_commit) > 1) { if (!mainline) return revert_seterr(revert_commit, - "Mainline branch is not specified but %s is a merge commit"); + "mainline branch is not specified but %s is a merge commit"); parent = mainline; } else { if (mainline) return revert_seterr(revert_commit, - "Mainline branch specified but %s is not a merge commit"); + "mainline branch specified but %s is not a merge commit"); parent = git_commit_parentcount(revert_commit); } diff --git a/src/revparse.c b/src/revparse.c index aa7e0bd98..d5511b47b 100644 --- a/src/revparse.c +++ b/src/revparse.c @@ -46,7 +46,7 @@ static int build_regex(regex_t *regex, const char *pattern) int error; if (*pattern == '\0') { - giterr_set(GITERR_REGEX, "Empty pattern"); + giterr_set(GITERR_REGEX, "empty pattern"); return GIT_EINVALIDSPEC; } @@ -118,7 +118,7 @@ static int revparse_lookup_object( if ((error = maybe_describe(object_out, repo, spec)) != GIT_ENOTFOUND) return error; - giterr_set(GITERR_REFERENCE, "Revspec '%s' not found.", spec); + giterr_set(GITERR_REFERENCE, "revspec '%s' not found", spec); return GIT_ENOTFOUND; } @@ -245,7 +245,7 @@ static int retrieve_oid_from_reflog(git_oid *oid, git_reference *ref, size_t ide notfound: giterr_set( GITERR_REFERENCE, - "Reflog for '%s' has only %"PRIuZ" entries, asked for %"PRIuZ, + "reflog for '%s' has only %"PRIuZ" entries, asked for %"PRIuZ, git_reference_name(ref), numentries, identifier); git_reflog_free(reflog); @@ -757,7 +757,7 @@ int revparse__ext( * TODO: support merge-stage path lookup (":2:Makefile") * and plain index blob lookup (:i-am/a/blob) */ - giterr_set(GITERR_INVALID, "Unimplemented"); + giterr_set(GITERR_INVALID, "unimplemented"); error = GIT_ERROR; goto cleanup; } @@ -816,7 +816,7 @@ cleanup: if (error) { if (error == GIT_EINVALIDSPEC) giterr_set(GITERR_INVALID, - "Failed to parse revision specifier - Invalid pattern '%s'", spec); + "failed to parse revision specifier - Invalid pattern '%s'", spec); git_object_free(base_rev); git_reference_free(reference); diff --git a/src/revwalk.c b/src/revwalk.c index f5502a72e..8c370bcc8 100644 --- a/src/revwalk.c +++ b/src/revwalk.c @@ -61,7 +61,7 @@ static int push_commit(git_revwalk *walk, const git_oid *oid, int uninteresting, if (from_glob) return 0; - giterr_set(GITERR_INVALID, "Object is not a committish"); + giterr_set(GITERR_INVALID, "object is not a committish"); return -1; } if (error < 0) @@ -198,7 +198,7 @@ int git_revwalk_push_range(git_revwalk *walk, const char *range) if (revspec.flags & GIT_REVPARSE_MERGE_BASE) { /* TODO: support "..." */ - giterr_set(GITERR_INVALID, "Symmetric differences not implemented in revwalk"); + giterr_set(GITERR_INVALID, "symmetric differences not implemented in revwalk"); return GIT_EINVALIDSPEC; } @@ -733,7 +733,7 @@ int git_revwalk_add_hide_cb( if (walk->hide_cb) { /* There is already a callback added */ - giterr_set(GITERR_INVALID, "There is already a callback added to hide commits in revision walker."); + giterr_set(GITERR_INVALID, "there is already a callback added to hide commits in revwalk"); return -1; } diff --git a/src/settings.c b/src/settings.c index 4a6e0f353..980233d88 100644 --- a/src/settings.c +++ b/src/settings.c @@ -64,7 +64,7 @@ static int config_level_to_sysdir(int config_level) break; default: giterr_set( - GITERR_INVALID, "Invalid config path selector %d", config_level); + GITERR_INVALID, "invalid config path selector %d", config_level); } return val; diff --git a/src/sha1_lookup.c b/src/sha1_lookup.c index c6b561340..ead26de06 100644 --- a/src/sha1_lookup.c +++ b/src/sha1_lookup.c @@ -206,7 +206,7 @@ int sha1_entry_pos(const void *table, #endif if (!(lo <= mi && mi < hi)) { - giterr_set(GITERR_INVALID, "Assertion failure. Binary search invariant is false"); + giterr_set(GITERR_INVALID, "assertion failure: binary search invariant is false"); return -1; } diff --git a/src/signature.c b/src/signature.c index 22cba7ef3..e792a52f8 100644 --- a/src/signature.c +++ b/src/signature.c @@ -25,7 +25,7 @@ void git_signature_free(git_signature *sig) static int signature_error(const char *msg) { - giterr_set(GITERR_INVALID, "Failed to parse signature - %s", msg); + giterr_set(GITERR_INVALID, "failed to parse signature - %s", msg); return -1; } diff --git a/src/socket_stream.c b/src/socket_stream.c index 71f49118e..fca411717 100644 --- a/src/socket_stream.c +++ b/src/socket_stream.c @@ -57,7 +57,7 @@ static int close_socket(GIT_SOCKET s) return -1; if (0 != WSACleanup()) { - giterr_set(GITERR_OS, "Winsock cleanup failed"); + giterr_set(GITERR_OS, "winsock cleanup failed"); return -1; } @@ -82,13 +82,13 @@ int socket_connect(git_stream *stream) WSADATA wsd; if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) { - giterr_set(GITERR_OS, "Winsock init failed"); + giterr_set(GITERR_OS, "winsock init failed"); return -1; } if (LOBYTE(wsd.wVersion) != 2 || HIBYTE(wsd.wVersion) != 2) { WSACleanup(); - giterr_set(GITERR_OS, "Winsock init failed"); + giterr_set(GITERR_OS, "winsock init failed"); return -1; } #endif @@ -99,7 +99,7 @@ int socket_connect(git_stream *stream) if ((ret = p_getaddrinfo(st->host, st->port, &hints, &info)) != 0) { giterr_set(GITERR_NET, - "Failed to resolve address for %s: %s", st->host, p_gai_strerror(ret)); + "failed to resolve address for %s: %s", st->host, p_gai_strerror(ret)); return -1; } @@ -121,7 +121,7 @@ int socket_connect(git_stream *stream) /* Oops, we couldn't connect to any address */ if (s == INVALID_SOCKET && p == NULL) { - giterr_set(GITERR_OS, "Failed to connect to %s", st->host); + giterr_set(GITERR_OS, "failed to connect to %s", st->host); p_freeaddrinfo(info); return -1; } diff --git a/src/sortedcache.c b/src/sortedcache.c index 5bd989a9f..c5e338f75 100644 --- a/src/sortedcache.c +++ b/src/sortedcache.c @@ -27,7 +27,7 @@ int git_sortedcache_new( goto fail; if (git_rwlock_init(&sc->lock)) { - giterr_set(GITERR_OS, "Failed to initialize lock"); + giterr_set(GITERR_OS, "failed to initialize lock"); goto fail; } @@ -162,7 +162,7 @@ int git_sortedcache_wlock(git_sortedcache *sc) GIT_UNUSED(sc); /* prevent warning when compiled w/o threads */ if (git_rwlock_wrlock(&sc->lock) < 0) { - giterr_set(GITERR_OS, "Unable to acquire write lock on cache"); + giterr_set(GITERR_OS, "unable to acquire write lock on cache"); return -1; } return 0; @@ -181,7 +181,7 @@ int git_sortedcache_rlock(git_sortedcache *sc) GIT_UNUSED(sc); /* prevent warning when compiled w/o threads */ if (git_rwlock_rdlock(&sc->lock) < 0) { - giterr_set(GITERR_OS, "Unable to acquire read lock on cache"); + giterr_set(GITERR_OS, "unable to acquire read lock on cache"); return -1; } return 0; @@ -221,7 +221,7 @@ int git_sortedcache_lockandload(git_sortedcache *sc, git_buf *buf) } if (!git__is_sizet(st.st_size)) { - giterr_set(GITERR_INVALID, "Unable to load file larger than size_t"); + giterr_set(GITERR_INVALID, "unable to load file larger than size_t"); error = -1; (void)p_close(fd); goto unlock; @@ -373,7 +373,7 @@ int git_sortedcache_remove(git_sortedcache *sc, size_t pos) */ if ((item = git_vector_get(&sc->items, pos)) == NULL) { - giterr_set(GITERR_INVALID, "Removing item out of range"); + giterr_set(GITERR_INVALID, "removing item out of range"); return GIT_ENOTFOUND; } diff --git a/src/stash.c b/src/stash.c index f5f4f36bf..d13220cdd 100644 --- a/src/stash.c +++ b/src/stash.c @@ -27,7 +27,7 @@ static int create_error(int error, const char *msg) { - giterr_set(GITERR_STASH, "Cannot stash changes - %s", msg); + giterr_set(GITERR_STASH, "cannot stash changes - %s", msg); return error; } @@ -36,7 +36,7 @@ static int retrieve_head(git_reference **out, git_repository *repo) int error = git_repository_head(out, repo); if (error == GIT_EUNBORNBRANCH) - return create_error(error, "You do not have the initial commit yet."); + return create_error(error, "you do not have the initial commit yet."); return error; } @@ -198,7 +198,7 @@ static int stash_update_index_from_diff( /* Unimplemented */ giterr_set( GITERR_INVALID, - "Cannot update index. Unimplemented status (%d)", + "cannot update index. Unimplemented status (%d)", delta->status); return -1; } @@ -479,7 +479,7 @@ static int ensure_there_are_changes_to_stash( return 0; if (!error) - return create_error(GIT_ENOTFOUND, "There is nothing to stash."); + return create_error(GIT_ENOTFOUND, "there is nothing to stash."); return error; } @@ -593,7 +593,7 @@ static int retrieve_stash_commit( max = git_reflog_entrycount(reflog); if (!max || index > max - 1) { error = GIT_ENOTFOUND; - giterr_set(GITERR_STASH, "No stashed state at position %" PRIuZ, index); + giterr_set(GITERR_STASH, "no stashed state at position %" PRIuZ, index); goto cleanup; } @@ -1036,7 +1036,7 @@ int git_stash_drop( if (!max || index > max - 1) { error = GIT_ENOTFOUND; - giterr_set(GITERR_STASH, "No stashed state at position %" PRIuZ, index); + giterr_set(GITERR_STASH, "no stashed state at position %" PRIuZ, index); goto cleanup; } diff --git a/src/status.c b/src/status.c index e610f5fe1..6752b5625 100644 --- a/src/status.c +++ b/src/status.c @@ -243,13 +243,13 @@ static int status_validate_options(const git_status_options *opts) GITERR_CHECK_VERSION(opts, GIT_STATUS_OPTIONS_VERSION, "git_status_options"); if (opts->show > GIT_STATUS_SHOW_WORKDIR_ONLY) { - giterr_set(GITERR_INVALID, "Unknown status 'show' option"); + giterr_set(GITERR_INVALID, "unknown status 'show' option"); return -1; } if ((opts->flags & GIT_STATUS_OPT_NO_REFRESH) != 0 && (opts->flags & GIT_STATUS_OPT_UPDATE_INDEX) != 0) { - giterr_set(GITERR_INVALID, "Updating index from status " + giterr_set(GITERR_INVALID, "updating index from status " "is not allowed when index refresh is disabled"); return -1; } @@ -510,13 +510,13 @@ int git_status_file( if (error < 0 && sfi.ambiguous) { giterr_set(GITERR_INVALID, - "Ambiguous path '%s' given to git_status_file", sfi.expected); + "ambiguous path '%s' given to git_status_file", sfi.expected); error = GIT_EAMBIGUOUS; } if (!error && !sfi.count) { giterr_set(GITERR_INVALID, - "Attempt to get status of nonexistent file '%s'", path); + "attempt to get status of nonexistent file '%s'", path); error = GIT_ENOTFOUND; } diff --git a/src/submodule.c b/src/submodule.c index 86ad53be0..6d6b314d6 100644 --- a/src/submodule.c +++ b/src/submodule.c @@ -124,8 +124,8 @@ static void submodule_set_lookup_error(int error, const char *name) return; giterr_set(GITERR_SUBMODULE, (error == GIT_ENOTFOUND) ? - "No submodule named '%s'" : - "Submodule '%s' has not been added yet", name); + "no submodule named '%s'" : + "submodule '%s' has not been added yet", name); } typedef struct { @@ -618,7 +618,7 @@ int git_submodule_add_setup( giterr_clear(); else { giterr_set(GITERR_SUBMODULE, - "Attempt to add submodule '%s' that already exists", path); + "attempt to add submodule '%s' that already exists", path); return GIT_EEXISTS; } @@ -628,7 +628,7 @@ int git_submodule_add_setup( path += strlen(git_repository_workdir(repo)); if (git_path_root(path) >= 0) { - giterr_set(GITERR_SUBMODULE, "Submodule path must be a relative path"); + giterr_set(GITERR_SUBMODULE, "submodule path must be a relative path"); error = -1; goto cleanup; } @@ -637,7 +637,7 @@ int git_submodule_add_setup( if (!(mods = open_gitmodules(repo, GITMODULES_CREATE))) { giterr_set(GITERR_SUBMODULE, - "Adding submodules to a bare repository is not supported"); + "adding submodules to a bare repository is not supported"); return -1; } @@ -758,7 +758,7 @@ int git_submodule_add_to_index(git_submodule *sm, int write_index) /* read stat information for submodule working directory */ if (p_stat(path.ptr, &st) < 0) { giterr_set(GITERR_SUBMODULE, - "Cannot add submodule without working directory"); + "cannot add submodule without working directory"); error = -1; goto cleanup; } @@ -771,7 +771,7 @@ int git_submodule_add_to_index(git_submodule *sm, int write_index) /* calling git_submodule_open will have set sm->wd_oid if possible */ if ((sm->flags & GIT_SUBMODULE_STATUS__WD_OID_VALID) == 0) { giterr_set(GITERR_SUBMODULE, - "Cannot add submodule without HEAD to index"); + "cannot add submodule without HEAD to index"); error = -1; goto cleanup; } @@ -861,7 +861,7 @@ int git_submodule_resolve_url(git_buf *out, git_repository *repo, const char *ur } else if (strchr(url, ':') != NULL || url[0] == '/') { error = git_buf_sets(out, url); } else { - giterr_set(GITERR_SUBMODULE, "Invalid format for submodule URL"); + giterr_set(GITERR_SUBMODULE, "invalid format for submodule URL"); error = -1; } @@ -1133,7 +1133,7 @@ int git_submodule_update(git_submodule *sm, int init, git_submodule_update_optio goto done; if (!init) { - giterr_set(GITERR_SUBMODULE, "Submodule is not initialized."); + giterr_set(GITERR_SUBMODULE, "submodule is not initialized"); error = GIT_ERROR; goto done; } @@ -1215,7 +1215,7 @@ int git_submodule_init(git_submodule *sm, int overwrite) if (!sm->url) { giterr_set(GITERR_SUBMODULE, - "No URL configured for submodule '%s'", sm->name); + "no URL configured for submodule '%s'", sm->name); return -1; } @@ -1259,7 +1259,7 @@ int git_submodule_sync(git_submodule *sm) if (!sm->url) { giterr_set(GITERR_SUBMODULE, - "No URL configured for submodule '%s'", sm->name); + "no URL configured for submodule '%s'", sm->name); return -1; } @@ -1578,7 +1578,7 @@ static int submodule_alloc( git_submodule *sm; if (!name || !(namelen = strlen(name))) { - giterr_set(GITERR_SUBMODULE, "Invalid submodule name"); + giterr_set(GITERR_SUBMODULE, "invalid submodule name"); return -1; } @@ -1630,7 +1630,7 @@ void git_submodule_free(git_submodule *sm) static int submodule_config_error(const char *property, const char *value) { giterr_set(GITERR_INVALID, - "Invalid value for submodule '%s' property: '%s'", property, value); + "invalid value for submodule '%s' property: '%s'", property, value); return -1; } @@ -1968,7 +1968,7 @@ static int lookup_default_remote(git_remote **remote, git_repository *repo) if (error == GIT_ENOTFOUND) giterr_set( GITERR_SUBMODULE, - "Cannot get default remote for submodule - no local tracking " + "cannot get default remote for submodule - no local tracking " "branch for HEAD and origin does not exist"); return error; diff --git a/src/sysdir.c b/src/sysdir.c index e89db7697..ed11221a3 100644 --- a/src/sysdir.c +++ b/src/sysdir.c @@ -150,7 +150,7 @@ int git_sysdir_get_str( GITERR_CHECK_ERROR(git_sysdir_get(&path, which)); if (!out || path->size >= outlen) { - giterr_set(GITERR_NOMEMORY, "Buffer is too short for the path"); + giterr_set(GITERR_NOMEMORY, "buffer is too short for the path"); return GIT_EBUFS; } @@ -241,7 +241,7 @@ static int git_sysdir_find_in_dirlist( done: git_buf_free(path); - giterr_set(GITERR_OS, "The %s file '%s' doesn't exist", label, name); + giterr_set(GITERR_OS, "the %s file '%s' doesn't exist", label, name); return GIT_ENOTFOUND; } diff --git a/src/tag.c b/src/tag.c index fe840fe82..2bf23fc3c 100644 --- a/src/tag.c +++ b/src/tag.c @@ -61,7 +61,7 @@ const char *git_tag_message(const git_tag *t) static int tag_error(const char *str) { - giterr_set(GITERR_TAG, "Failed to parse tag. %s", str); + giterr_set(GITERR_TAG, "failed to parse tag: %s", str); return -1; } @@ -76,13 +76,13 @@ static int tag_parse(git_tag *tag, const char *buffer, const char *buffer_end) char *search; if (git_oid__parse(&tag->target, &buffer, buffer_end, "object ") < 0) - return tag_error("Object field invalid"); + return tag_error("object field invalid"); if (buffer + 5 >= buffer_end) - return tag_error("Object too short"); + return tag_error("object too short"); if (memcmp(buffer, "type ", 5) != 0) - return tag_error("Type field not found"); + return tag_error("type field not found"); buffer += 5; tag->type = GIT_OBJ_BAD; @@ -91,7 +91,7 @@ static int tag_parse(git_tag *tag, const char *buffer, const char *buffer_end) size_t type_length = strlen(tag_types[i]); if (buffer + type_length >= buffer_end) - return tag_error("Object too short"); + return tag_error("object too short"); if (memcmp(buffer, tag_types[i], type_length) == 0) { tag->type = i; @@ -101,19 +101,19 @@ static int tag_parse(git_tag *tag, const char *buffer, const char *buffer_end) } if (tag->type == GIT_OBJ_BAD) - return tag_error("Invalid object type"); + return tag_error("invalid object type"); if (buffer + 4 >= buffer_end) - return tag_error("Object too short"); + return tag_error("object too short"); if (memcmp(buffer, "tag ", 4) != 0) - return tag_error("Tag field not found"); + return tag_error("tag field not found"); buffer += 4; search = memchr(buffer, '\n', buffer_end - buffer); if (search == NULL) - return tag_error("Object too short"); + return tag_error("object too short"); text_len = search - buffer; @@ -234,7 +234,7 @@ static int write_tag_annotation( on_error: git_buf_free(&tag); - giterr_set(GITERR_OBJECT, "Failed to create tag annotation."); + giterr_set(GITERR_OBJECT, "failed to create tag annotation"); return -1; } @@ -257,7 +257,7 @@ static int git_tag_create__internal( assert(!create_tag_annotation || (tagger && message)); if (git_object_owner(target) != repo) { - giterr_set(GITERR_INVALID, "The given target does not belong to this repository"); + giterr_set(GITERR_INVALID, "the given target does not belong to this repository"); return -1; } @@ -269,7 +269,7 @@ static int git_tag_create__internal( * reference unless overwriting has explicitly been requested **/ if (error == 0 && !allow_ref_overwrite) { git_buf_free(&ref_name); - giterr_set(GITERR_TAG, "Tag already exists"); + giterr_set(GITERR_TAG, "tag already exists"); return GIT_EEXISTS; } @@ -349,7 +349,7 @@ int git_tag_create_frombuffer(git_oid *oid, git_repository *repo, const char *bu goto on_error; if (tag.type != target_obj->cached.type) { - giterr_set(GITERR_TAG, "The type for the given target is invalid"); + giterr_set(GITERR_TAG, "the type for the given target is invalid"); goto on_error; } @@ -366,7 +366,7 @@ int git_tag_create_frombuffer(git_oid *oid, git_repository *repo, const char *bu /** Ensure the tag name doesn't conflict with an already existing * reference unless overwriting has explicitly been requested **/ if (error == 0 && !allow_ref_overwrite) { - giterr_set(GITERR_TAG, "Tag already exists"); + giterr_set(GITERR_TAG, "tag already exists"); return GIT_EEXISTS; } diff --git a/src/trace.c b/src/trace.c index ee5039f56..0f2142861 100644 --- a/src/trace.c +++ b/src/trace.c @@ -32,7 +32,7 @@ int git_trace_set(git_trace_level_t level, git_trace_callback callback) GIT_UNUSED(callback); giterr_set(GITERR_INVALID, - "This version of libgit2 was not built with tracing."); + "this version of libgit2 was not built with tracing."); return -1; #endif } diff --git a/src/transport.c b/src/transport.c index f08d2dc68..b66165332 100644 --- a/src/transport.c +++ b/src/transport.c @@ -121,7 +121,7 @@ int git_transport_new(git_transport **out, git_remote *owner, const char *url) int error; if ((error = transport_find_fn(&fn, url, ¶m)) == GIT_ENOTFOUND) { - giterr_set(GITERR_NET, "Unsupported URL protocol"); + giterr_set(GITERR_NET, "unsupported URL protocol"); return -1; } else if (error < 0) return error; diff --git a/src/transports/auth_negotiate.c b/src/transports/auth_negotiate.c index 8b99fc735..7c868c9fd 100644 --- a/src/transports/auth_negotiate.c +++ b/src/transports/auth_negotiate.c @@ -107,13 +107,13 @@ static int negotiate_next_token( challenge_len = ctx->challenge ? strlen(ctx->challenge) : 0; if (challenge_len < 9) { - giterr_set(GITERR_NET, "No negotiate challenge sent from server"); + giterr_set(GITERR_NET, "no negotiate challenge sent from server"); error = -1; goto done; } else if (challenge_len > 9) { if (git_buf_decode_base64(&input_buf, ctx->challenge + 10, challenge_len - 10) < 0) { - giterr_set(GITERR_NET, "Invalid negotiate challenge from server"); + giterr_set(GITERR_NET, "invalid negotiate challenge from server"); error = -1; goto done; } @@ -122,7 +122,7 @@ static int negotiate_next_token( input_token.length = input_buf.size; input_token_ptr = &input_token; } else if (ctx->gss_context != GSS_C_NO_CONTEXT) { - giterr_set(GITERR_NET, "Could not restart authentication"); + giterr_set(GITERR_NET, "could not restart authentication"); error = -1; goto done; } @@ -228,7 +228,7 @@ static int negotiate_init_context( gss_release_oid_set(&status_minor, &mechanism_list); if (!ctx->oid) { - giterr_set(GITERR_NET, "Negotiate authentication is not supported"); + giterr_set(GITERR_NET, "negotiate authentication is not supported"); return -1; } diff --git a/src/transports/cred.c b/src/transports/cred.c index 49ede48bf..8e3f64435 100644 --- a/src/transports/cred.c +++ b/src/transports/cred.c @@ -216,7 +216,7 @@ int git_cred_ssh_key_memory_new( GIT_UNUSED(passphrase); giterr_set(GITERR_INVALID, - "This version of libgit2 was not built with ssh memory credentials."); + "this version of libgit2 was not built with ssh memory credentials."); return -1; #endif } diff --git a/src/transports/git.c b/src/transports/git.c index 6c6acf9c5..01edfdc49 100644 --- a/src/transports/git.c +++ b/src/transports/git.c @@ -45,7 +45,7 @@ static int gen_proto(git_buf *request, const char *cmd, const char *url) delim = strchr(url, '/'); if (delim == NULL) { - giterr_set(GITERR_NET, "Malformed URL"); + giterr_set(GITERR_NET, "malformed URL"); return -1; } @@ -240,7 +240,7 @@ static int _git_uploadpack( return 0; } - giterr_set(GITERR_NET, "Must call UPLOADPACK_LS before UPLOADPACK"); + giterr_set(GITERR_NET, "must call UPLOADPACK_LS before UPLOADPACK"); return -1; } @@ -296,7 +296,7 @@ static int _git_receivepack( return 0; } - giterr_set(GITERR_NET, "Must call RECEIVEPACK_LS before RECEIVEPACK"); + giterr_set(GITERR_NET, "must call RECEIVEPACK_LS before RECEIVEPACK"); return -1; } diff --git a/src/transports/http.c b/src/transports/http.c index ad28c5889..9edbee551 100644 --- a/src/transports/http.c +++ b/src/transports/http.c @@ -403,7 +403,7 @@ static int on_headers_complete(http_parser *parser) t->location) { if (s->redirect_count >= 7) { - giterr_set(GITERR_NET, "Too many redirects"); + giterr_set(GITERR_NET, "too many redirects"); return t->parse_error = PARSE_ERROR_GENERIC; } @@ -428,14 +428,14 @@ static int on_headers_complete(http_parser *parser) /* Check for a 200 HTTP status code. */ if (parser->status_code != 200) { giterr_set(GITERR_NET, - "Unexpected HTTP status code: %d", + "unexpected HTTP status code: %d", parser->status_code); return t->parse_error = PARSE_ERROR_GENERIC; } /* The response must contain a Content-Type header. */ if (!t->content_type) { - giterr_set(GITERR_NET, "No Content-Type header in response"); + giterr_set(GITERR_NET, "no Content-Type header in response"); return t->parse_error = PARSE_ERROR_GENERIC; } @@ -455,7 +455,7 @@ static int on_headers_complete(http_parser *parser) if (strcmp(t->content_type, git_buf_cstr(&buf))) { git_buf_free(&buf); giterr_set(GITERR_NET, - "Invalid Content-Type: %s", + "invalid Content-Type: %s", t->content_type); return t->parse_error = PARSE_ERROR_GENERIC; } @@ -488,7 +488,7 @@ static int on_body_fill_buffer(http_parser *parser, const char *str, size_t len) return 0; if (ctx->buf_size < len) { - giterr_set(GITERR_NET, "Can't fit data in the buffer"); + giterr_set(GITERR_NET, "can't fit data in the buffer"); return t->parse_error = PARSE_ERROR_GENERIC; } @@ -857,7 +857,7 @@ static int http_stream_write_single( assert(t->connected); if (s->sent_request) { - giterr_set(GITERR_NET, "Subtransport configured for only one write"); + giterr_set(GITERR_NET, "subtransport configured for only one write"); return -1; } diff --git a/src/transports/local.c b/src/transports/local.c index 4eae9dead..87745add5 100644 --- a/src/transports/local.c +++ b/src/transports/local.c @@ -252,7 +252,7 @@ static int local_ls(const git_remote_head ***out, size_t *size, git_transport *t transport_local *t = (transport_local *)transport; if (!t->have_refs) { - giterr_set(GITERR_NET, "The transport has not yet loaded the refs"); + giterr_set(GITERR_NET, "the transport has not yet loaded the refs"); return -1; } @@ -371,7 +371,7 @@ static int local_push( but we forbid all pushes just in case */ if (!remote_repo->is_bare) { error = GIT_EBAREREPO; - giterr_set(GITERR_INVALID, "Local push doesn't (yet) support pushing to non-bare repos."); + giterr_set(GITERR_INVALID, "local push doesn't (yet) support pushing to non-bare repos."); goto on_error; } diff --git a/src/transports/smart.c b/src/transports/smart.c index 7a35c39d8..e4aa26d86 100644 --- a/src/transports/smart.c +++ b/src/transports/smart.c @@ -231,7 +231,7 @@ static int git_smart__connect( else if (GIT_DIRECTION_PUSH == t->direction) service = GIT_SERVICE_RECEIVEPACK_LS; else { - giterr_set(GITERR_NET, "Invalid direction"); + giterr_set(GITERR_NET, "invalid direction"); return -1; } @@ -252,7 +252,7 @@ static int git_smart__connect( pkt = (git_pkt *)git_vector_get(&t->refs, 0); if (!pkt || GIT_PKT_COMMENT != pkt->type) { - giterr_set(GITERR_NET, "Invalid response"); + giterr_set(GITERR_NET, "invalid response"); return -1; } else { /* Remove the comment pkt from the list */ @@ -299,7 +299,7 @@ static int git_smart__ls(const git_remote_head ***out, size_t *size, git_transpo transport_smart *t = (transport_smart *)transport; if (!t->have_refs) { - giterr_set(GITERR_NET, "The transport has not yet loaded the refs"); + giterr_set(GITERR_NET, "the transport has not yet loaded the refs"); return -1; } @@ -319,7 +319,7 @@ int git_smart__negotiation_step(git_transport *transport, void *data, size_t len return -1; if (GIT_DIRECTION_FETCH != t->direction) { - giterr_set(GITERR_NET, "This operation is only valid for fetch"); + giterr_set(GITERR_NET, "this operation is only valid for fetch"); return -1; } @@ -348,7 +348,7 @@ int git_smart__get_push_stream(transport_smart *t, git_smart_subtransport_stream return -1; if (GIT_DIRECTION_PUSH != t->direction) { - giterr_set(GITERR_NET, "This operation is only valid for push"); + giterr_set(GITERR_NET, "this operation is only valid for push"); return -1; } diff --git a/src/transports/smart_pkt.c b/src/transports/smart_pkt.c index 2297cc94f..c0672e25a 100644 --- a/src/transports/smart_pkt.c +++ b/src/transports/smart_pkt.c @@ -226,7 +226,7 @@ static int ref_pkt(git_pkt **out, const char *line, size_t len) /* Check for a bit of consistency */ if (line[GIT_OID_HEXSZ] != ' ') { - giterr_set(GITERR_NET, "Error parsing pkt-line"); + giterr_set(GITERR_NET, "error parsing pkt-line"); error = -1; goto error_out; } @@ -270,7 +270,7 @@ static int ok_pkt(git_pkt **out, const char *line, size_t len) line += 3; /* skip "ok " */ if (!(ptr = strchr(line, '\n'))) { - giterr_set(GITERR_NET, "Invalid packet line"); + giterr_set(GITERR_NET, "invalid packet line"); git__free(pkt); return -1; } @@ -327,7 +327,7 @@ static int ng_pkt(git_pkt **out, const char *line, size_t len) return 0; out_err: - giterr_set(GITERR_NET, "Invalid packet line"); + giterr_set(GITERR_NET, "invalid packet line"); git__free(pkt->ref); git__free(pkt); return -1; @@ -535,7 +535,7 @@ static int buffer_want_with_caps(const git_remote_head *head, transport_smart_ca if (len > 0xffff) { giterr_set(GITERR_NET, - "Tried to produce packet with invalid length %" PRIuZ, len); + "tried to produce packet with invalid length %" PRIuZ, len); return -1; } diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c index 53c0b089e..b29818d3f 100644 --- a/src/transports/smart_protocol.c +++ b/src/transports/smart_protocol.c @@ -60,7 +60,7 @@ int git_smart__store_refs(transport_smart *t, int flushes) gitno_consume(buf, line_end); if (pkt->type == GIT_PKT_ERR) { - giterr_set(GITERR_NET, "Remote error: %s", ((git_pkt_err *)pkt)->error); + giterr_set(GITERR_NET, "remote error: %s", ((git_pkt_err *)pkt)->error); git__free(pkt); return -1; } diff --git a/src/transports/ssh.c b/src/transports/ssh.c index cfd573665..44d02e522 100644 --- a/src/transports/ssh.c +++ b/src/transports/ssh.c @@ -83,7 +83,7 @@ static int gen_proto(git_buf *request, const char *cmd, const char *url) done: if (!repo) { - giterr_set(GITERR_NET, "Malformed git protocol URL"); + giterr_set(GITERR_NET, "malformed git protocol URL"); return -1; } @@ -274,7 +274,7 @@ static int git_ssh_extract_url_parts( } if (colon == NULL || (colon < start)) { - giterr_set(GITERR_NET, "Malformed URL"); + giterr_set(GITERR_NET, "malformed URL"); return -1; } @@ -445,7 +445,7 @@ static int request_creds(git_cred **out, ssh_subtransport *t, const char *user, else if (error < 0) return error; else if (!cred) { - giterr_set(GITERR_SSH, "Callback failed to initialize SSH credentials"); + giterr_set(GITERR_SSH, "callback failed to initialize SSH credentials"); return -1; } } @@ -478,7 +478,7 @@ static int _git_ssh_session_create( s = libssh2_session_init(); if (!s) { - giterr_set(GITERR_NET, "Failed to initialize SSH session"); + giterr_set(GITERR_NET, "failed to initialize SSH session"); return -1; } @@ -487,7 +487,7 @@ static int _git_ssh_session_create( } while (LIBSSH2_ERROR_EAGAIN == rc || LIBSSH2_ERROR_TIMEOUT == rc); if (rc != LIBSSH2_ERROR_NONE) { - ssh_error(s, "Failed to start SSH session"); + ssh_error(s, "failed to start SSH session"); libssh2_session_free(s); return -1; } @@ -685,7 +685,7 @@ static int ssh_uploadpack( return 0; } - giterr_set(GITERR_NET, "Must call UPLOADPACK_LS before UPLOADPACK"); + giterr_set(GITERR_NET, "must call UPLOADPACK_LS before UPLOADPACK"); return -1; } @@ -712,7 +712,7 @@ static int ssh_receivepack( return 0; } - giterr_set(GITERR_NET, "Must call RECEIVEPACK_LS before RECEIVEPACK"); + giterr_set(GITERR_NET, "must call RECEIVEPACK_LS before RECEIVEPACK"); return -1; } @@ -844,7 +844,7 @@ int git_smart_subtransport_ssh( assert(out); *out = NULL; - giterr_set(GITERR_INVALID, "Cannot create SSH transport. Library was built without SSH support"); + giterr_set(GITERR_INVALID, "cannot create SSH transport. Library was built without SSH support"); return -1; #endif } @@ -888,7 +888,7 @@ int git_transport_ssh_with_paths(git_transport **out, git_remote *owner, void *p assert(out); *out = NULL; - giterr_set(GITERR_INVALID, "Cannot create SSH transport. Library was built without SSH support"); + giterr_set(GITERR_INVALID, "cannot create SSH transport. Library was built without SSH support"); return -1; #endif } diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c index 78e42cf3b..051340d87 100644 --- a/src/transports/winhttp.c +++ b/src/transports/winhttp.c @@ -139,12 +139,12 @@ static int apply_basic_credential(HINTERNET request, git_cred *cred) goto on_error; if ((wide_len = git__utf8_to_16_alloc(&wide, git_buf_cstr(&buf))) < 0) { - giterr_set(GITERR_OS, "Failed to convert string to wide form"); + giterr_set(GITERR_OS, "failed to convert string to wide form"); goto on_error; } if (!WinHttpAddRequestHeaders(request, wide, (ULONG) -1L, WINHTTP_ADDREQ_FLAG_ADD)) { - giterr_set(GITERR_OS, "Failed to add a header to the request"); + giterr_set(GITERR_OS, "failed to add a header to the request"); goto on_error; } @@ -202,7 +202,7 @@ static int fallback_cred_acquire_cb( /* Convert URL to wide characters */ if (git__utf8_to_16_alloc(&wide_url, url) < 0) { - giterr_set(GITERR_OS, "Failed to convert string to wide form"); + giterr_set(GITERR_OS, "failed to convert string to wide form"); return -1; } @@ -351,7 +351,7 @@ static int winhttp_stream_connect(winhttp_stream *s) /* Convert URL to wide characters */ if (git__utf8_to_16_alloc(&s->request_uri, git_buf_cstr(&buf)) < 0) { - giterr_set(GITERR_OS, "Failed to convert string to wide form"); + giterr_set(GITERR_OS, "failed to convert string to wide form"); goto on_error; } @@ -366,12 +366,12 @@ static int winhttp_stream_connect(winhttp_stream *s) t->connection_data.use_ssl ? WINHTTP_FLAG_SECURE : 0); if (!s->request) { - giterr_set(GITERR_OS, "Failed to open request"); + giterr_set(GITERR_OS, "failed to open request"); goto on_error; } if (!WinHttpSetTimeouts(s->request, default_timeout, default_connect_timeout, default_timeout, default_timeout)) { - giterr_set(GITERR_OS, "Failed to set timeouts for WinHTTP"); + giterr_set(GITERR_OS, "failed to set timeouts for WinHTTP"); goto on_error; } @@ -444,7 +444,7 @@ static int winhttp_stream_connect(winhttp_stream *s) WINHTTP_OPTION_PROXY, &proxy_info, sizeof(WINHTTP_PROXY_INFO))) { - giterr_set(GITERR_OS, "Failed to set proxy"); + giterr_set(GITERR_OS, "failed to set proxy"); git__free(proxy_wide); goto on_error; } @@ -467,7 +467,7 @@ static int winhttp_stream_connect(winhttp_stream *s) WINHTTP_OPTION_DISABLE_FEATURE, &disable_redirects, sizeof(disable_redirects))) { - giterr_set(GITERR_OS, "Failed to disable redirects"); + giterr_set(GITERR_OS, "failed to disable redirects"); goto on_error; } @@ -481,7 +481,7 @@ static int winhttp_stream_connect(winhttp_stream *s) /* Send Pragma: no-cache header */ if (!WinHttpAddRequestHeaders(s->request, pragma_nocache, (ULONG) -1L, WINHTTP_ADDREQ_FLAG_ADD)) { - giterr_set(GITERR_OS, "Failed to add a header to the request"); + giterr_set(GITERR_OS, "failed to add a header to the request"); goto on_error; } @@ -494,13 +494,13 @@ static int winhttp_stream_connect(winhttp_stream *s) goto on_error; if (git__utf8_to_16(ct, MAX_CONTENT_TYPE_LEN, git_buf_cstr(&buf)) < 0) { - giterr_set(GITERR_OS, "Failed to convert content-type to wide characters"); + giterr_set(GITERR_OS, "failed to convert content-type to wide characters"); goto on_error; } if (!WinHttpAddRequestHeaders(s->request, ct, (ULONG)-1L, WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE)) { - giterr_set(GITERR_OS, "Failed to add a header to the request"); + giterr_set(GITERR_OS, "failed to add a header to the request"); goto on_error; } @@ -511,13 +511,13 @@ static int winhttp_stream_connect(winhttp_stream *s) goto on_error; if (git__utf8_to_16(ct, MAX_CONTENT_TYPE_LEN, git_buf_cstr(&buf)) < 0) { - giterr_set(GITERR_OS, "Failed to convert accept header to wide characters"); + giterr_set(GITERR_OS, "failed to convert accept header to wide characters"); goto on_error; } if (!WinHttpAddRequestHeaders(s->request, ct, (ULONG)-1L, WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE)) { - giterr_set(GITERR_OS, "Failed to add a header to the request"); + giterr_set(GITERR_OS, "failed to add a header to the request"); goto on_error; } } @@ -527,13 +527,13 @@ static int winhttp_stream_connect(winhttp_stream *s) git_buf_clear(&buf); git_buf_puts(&buf, t->owner->custom_headers.strings[i]); if (git__utf8_to_16(ct, MAX_CONTENT_TYPE_LEN, git_buf_cstr(&buf)) < 0) { - giterr_set(GITERR_OS, "Failed to convert custom header to wide characters"); + giterr_set(GITERR_OS, "failed to convert custom header to wide characters"); goto on_error; } if (!WinHttpAddRequestHeaders(s->request, ct, (ULONG)-1L, WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE)) { - giterr_set(GITERR_OS, "Failed to add a header to the request"); + giterr_set(GITERR_OS, "failed to add a header to the request"); goto on_error; } } @@ -596,7 +596,7 @@ static int parse_unauthorized_response( * We can assume this was already done, since we know we are unauthorized. */ if (!WinHttpQueryAuthSchemes(request, &supported, &first, &target)) { - giterr_set(GITERR_OS, "Failed to parse supported auth schemes"); + giterr_set(GITERR_OS, "failed to parse supported auth schemes"); return -1; } @@ -629,7 +629,7 @@ static int write_chunk(HINTERNET request, const char *buffer, size_t len) git_buf_cstr(&buf), (DWORD)git_buf_len(&buf), &bytes_written)) { git_buf_free(&buf); - giterr_set(GITERR_OS, "Failed to write chunk header"); + giterr_set(GITERR_OS, "failed to write chunk header"); return -1; } @@ -639,7 +639,7 @@ static int write_chunk(HINTERNET request, const char *buffer, size_t len) if (!WinHttpWriteData(request, buffer, (DWORD)len, &bytes_written)) { - giterr_set(GITERR_OS, "Failed to write chunk"); + giterr_set(GITERR_OS, "failed to write chunk"); return -1; } @@ -647,7 +647,7 @@ static int write_chunk(HINTERNET request, const char *buffer, size_t len) if (!WinHttpWriteData(request, "\r\n", 2, &bytes_written)) { - giterr_set(GITERR_OS, "Failed to write chunk footer"); + giterr_set(GITERR_OS, "failed to write chunk footer"); return -1; } @@ -660,7 +660,7 @@ static int winhttp_close_connection(winhttp_subtransport *t) if (t->connection) { if (!WinHttpCloseHandle(t->connection)) { - giterr_set(GITERR_OS, "Unable to close connection"); + giterr_set(GITERR_OS, "unable to close connection"); ret = -1; } @@ -669,7 +669,7 @@ static int winhttp_close_connection(winhttp_subtransport *t) if (t->session) { if (!WinHttpCloseHandle(t->session)) { - giterr_set(GITERR_OS, "Unable to close session"); + giterr_set(GITERR_OS, "unable to close session"); ret = -1; } @@ -714,7 +714,7 @@ static int winhttp_connect( /* Prepare host */ if (git__utf8_to_16_alloc(&wide_host, t->connection_data.host) < 0) { - giterr_set(GITERR_OS, "Unable to convert host to wide characters"); + giterr_set(GITERR_OS, "unable to convert host to wide characters"); return -1; } @@ -724,7 +724,7 @@ static int winhttp_connect( } if (git__utf8_to_16_alloc(&wide_ua, git_buf_cstr(&ua)) < 0) { - giterr_set(GITERR_OS, "Unable to convert host to wide characters"); + giterr_set(GITERR_OS, "unable to convert host to wide characters"); git__free(wide_host); git_buf_free(&ua); return -1; @@ -741,12 +741,12 @@ static int winhttp_connect( 0); if (!t->session) { - giterr_set(GITERR_OS, "Failed to init WinHTTP"); + giterr_set(GITERR_OS, "failed to init WinHTTP"); goto on_error; } if (!WinHttpSetTimeouts(t->session, default_timeout, default_connect_timeout, default_timeout, default_timeout)) { - giterr_set(GITERR_OS, "Failed to set timeouts for WinHTTP"); + giterr_set(GITERR_OS, "failed to set timeouts for WinHTTP"); goto on_error; } @@ -759,7 +759,7 @@ static int winhttp_connect( 0); if (!t->connection) { - giterr_set(GITERR_OS, "Failed to connect to host"); + giterr_set(GITERR_OS, "failed to connect to host"); goto on_error; } @@ -853,7 +853,7 @@ static int winhttp_stream_read( replay: /* Enforce a reasonable cap on the number of replays */ if (++replay_count >= 7) { - giterr_set(GITERR_NET, "Too many redirects or authentication replays"); + giterr_set(GITERR_NET, "too many redirects or authentication replays"); return -1; } @@ -888,7 +888,7 @@ replay: if (!WinHttpWriteData(s->request, "0\r\n\r\n", 5, &bytes_written)) { - giterr_set(GITERR_OS, "Failed to write final chunk"); + giterr_set(GITERR_OS, "failed to write final chunk"); return -1; } } @@ -899,7 +899,7 @@ replay: if (INVALID_SET_FILE_POINTER == SetFilePointer(s->post_body, 0, 0, FILE_BEGIN) && NO_ERROR != GetLastError()) { - giterr_set(GITERR_OS, "Failed to reset file pointer"); + giterr_set(GITERR_OS, "failed to reset file pointer"); return -1; } @@ -913,14 +913,14 @@ replay: &bytes_read, NULL) || !bytes_read) { git__free(buffer); - giterr_set(GITERR_OS, "Failed to read from temp file"); + giterr_set(GITERR_OS, "failed to read from temp file"); return -1; } if (!WinHttpWriteData(s->request, buffer, bytes_read, &bytes_written)) { git__free(buffer); - giterr_set(GITERR_OS, "Failed to write data"); + giterr_set(GITERR_OS, "failed to write data"); return -1; } @@ -936,7 +936,7 @@ replay: } if (!WinHttpReceiveResponse(s->request, 0)) { - giterr_set(GITERR_OS, "Failed to receive response"); + giterr_set(GITERR_OS, "failed to receive response"); return -1; } @@ -948,7 +948,7 @@ replay: WINHTTP_HEADER_NAME_BY_INDEX, &status_code, &status_code_length, WINHTTP_NO_HEADER_INDEX)) { - giterr_set(GITERR_OS, "Failed to retrieve status code"); + giterr_set(GITERR_OS, "failed to retrieve status code"); return -1; } @@ -978,7 +978,7 @@ replay: &location_length, WINHTTP_NO_HEADER_INDEX) || GetLastError() != ERROR_INSUFFICIENT_BUFFER) { - giterr_set(GITERR_OS, "Failed to read Location header"); + giterr_set(GITERR_OS, "failed to read Location header"); return -1; } @@ -991,14 +991,14 @@ replay: location, &location_length, WINHTTP_NO_HEADER_INDEX)) { - giterr_set(GITERR_OS, "Failed to read Location header"); + giterr_set(GITERR_OS, "failed to read Location header"); git__free(location); return -1; } /* Convert the Location header to UTF-8 */ if (git__utf16_to_8_alloc(&location8, location) < 0) { - giterr_set(GITERR_OS, "Failed to convert Location header to UTF-8"); + giterr_set(GITERR_OS, "failed to convert Location header to UTF-8"); git__free(location); return -1; } @@ -1090,7 +1090,7 @@ replay: } if (HTTP_STATUS_OK != status_code) { - giterr_set(GITERR_NET, "Request failed with status code: %d", status_code); + giterr_set(GITERR_NET, "request failed with status code: %d", status_code); return -1; } @@ -1101,7 +1101,7 @@ replay: p_snprintf(expected_content_type_8, MAX_CONTENT_TYPE_LEN, "application/x-git-%s-advertisement", s->service); if (git__utf8_to_16(expected_content_type, MAX_CONTENT_TYPE_LEN, expected_content_type_8) < 0) { - giterr_set(GITERR_OS, "Failed to convert expected content-type to wide characters"); + giterr_set(GITERR_OS, "failed to convert expected content-type to wide characters"); return -1; } @@ -1112,12 +1112,12 @@ replay: WINHTTP_HEADER_NAME_BY_INDEX, &content_type, &content_type_length, WINHTTP_NO_HEADER_INDEX)) { - giterr_set(GITERR_OS, "Failed to retrieve response content-type"); + giterr_set(GITERR_OS, "failed to retrieve response content-type"); return -1; } if (wcscmp(expected_content_type, content_type)) { - giterr_set(GITERR_NET, "Received unexpected content-type"); + giterr_set(GITERR_NET, "received unexpected content-type"); return -1; } @@ -1129,7 +1129,7 @@ replay: (DWORD)buf_size, &dw_bytes_read)) { - giterr_set(GITERR_OS, "Failed to read data"); + giterr_set(GITERR_OS, "failed to read data"); return -1; } @@ -1152,7 +1152,7 @@ static int winhttp_stream_write_single( /* This implementation of write permits only a single call. */ if (s->sent_request) { - giterr_set(GITERR_NET, "Subtransport configured for only one write"); + giterr_set(GITERR_NET, "subtransport configured for only one write"); return -1; } @@ -1165,7 +1165,7 @@ static int winhttp_stream_write_single( (LPCVOID)buffer, (DWORD)len, &bytes_written)) { - giterr_set(GITERR_OS, "Failed to write data"); + giterr_set(GITERR_OS, "failed to write data"); return -1; } @@ -1183,12 +1183,12 @@ static int put_uuid_string(LPWSTR buffer, size_t buffer_len_cch) if (RPC_S_OK != status && RPC_S_UUID_LOCAL_ONLY != status && RPC_S_UUID_NO_ADDRESS != status) { - giterr_set(GITERR_NET, "Unable to generate name for temp file"); + giterr_set(GITERR_NET, "unable to generate name for temp file"); return -1; } if (buffer_len_cch < UUID_LENGTH_CCH + 1) { - giterr_set(GITERR_NET, "Buffer too small for name of temp file"); + giterr_set(GITERR_NET, "buffer too small for name of temp file"); return -1; } @@ -1203,7 +1203,7 @@ static int put_uuid_string(LPWSTR buffer, size_t buffer_len_cch) uuid.Data4[4], uuid.Data4[5], uuid.Data4[6], uuid.Data4[7]); if (result < UUID_LENGTH_CCH) { - giterr_set(GITERR_OS, "Unable to generate name for temp file"); + giterr_set(GITERR_OS, "unable to generate name for temp file"); return -1; } @@ -1215,7 +1215,7 @@ static int get_temp_file(LPWSTR buffer, DWORD buffer_len_cch) size_t len; if (!GetTempPathW(buffer_len_cch, buffer)) { - giterr_set(GITERR_OS, "Failed to get temp path"); + giterr_set(GITERR_OS, "failed to get temp path"); return -1; } @@ -1258,13 +1258,13 @@ static int winhttp_stream_write_buffered( if (INVALID_HANDLE_VALUE == s->post_body) { s->post_body = NULL; - giterr_set(GITERR_OS, "Failed to create temporary file"); + giterr_set(GITERR_OS, "failed to create temporary file"); return -1; } } if (!WriteFile(s->post_body, buffer, (DWORD)len, &bytes_written, NULL)) { - giterr_set(GITERR_OS, "Failed to write to temporary file"); + giterr_set(GITERR_OS, "failed to write to temporary file"); return -1; } @@ -1291,7 +1291,7 @@ static int winhttp_stream_write_chunked( if (!WinHttpAddRequestHeaders(s->request, transfer_encoding, (ULONG) -1L, WINHTTP_ADDREQ_FLAG_ADD)) { - giterr_set(GITERR_OS, "Failed to add a header to the request"); + giterr_set(GITERR_OS, "failed to add a header to the request"); return -1; } diff --git a/src/tree-cache.c b/src/tree-cache.c index b37be0f0d..548054136 100644 --- a/src/tree-cache.c +++ b/src/tree-cache.c @@ -137,7 +137,7 @@ static int read_tree_internal(git_tree_cache **out, return 0; corrupted: - giterr_set(GITERR_INDEX, "Corrupted TREE extension in index"); + giterr_set(GITERR_INDEX, "corrupted TREE extension in index"); return -1; } @@ -149,7 +149,7 @@ int git_tree_cache_read(git_tree_cache **tree, const char *buffer, size_t buffer return -1; if (buffer < buffer_end) { - giterr_set(GITERR_INDEX, "Corrupted TREE extension in index (unexpected trailing data)"); + giterr_set(GITERR_INDEX, "corrupted TREE extension in index (unexpected trailing data)"); return -1; } diff --git a/src/tree.c b/src/tree.c index 9655ad739..783dca41f 100644 --- a/src/tree.c +++ b/src/tree.c @@ -627,7 +627,7 @@ int git_tree__write_index( if (git_index_has_conflicts(index)) { giterr_set(GITERR_INDEX, - "Cannot create a tree from a not fully merged index."); + "cannot create a tree from a not fully merged index."); return GIT_EUNMERGED; } @@ -909,7 +909,7 @@ int git_tree_entry_bypath( filename_len = subpath_len(path); if (filename_len == 0) { - giterr_set(GITERR_TREE, "Invalid tree path given"); + giterr_set(GITERR_TREE, "invalid tree path given"); return GIT_ENOTFOUND; } @@ -1027,7 +1027,7 @@ int git_tree_walk( git_buf root_path = GIT_BUF_INIT; if (mode != GIT_TREEWALK_POST && mode != GIT_TREEWALK_PRE) { - giterr_set(GITERR_INVALID, "Invalid walking mode for tree walk"); + giterr_set(GITERR_INVALID, "invalid walking mode for tree walk"); return -1; } @@ -1237,7 +1237,7 @@ int git_tree_create_updated(git_oid *out, git_repository *repo, git_tree *baseli const git_tree_entry *e = git_treebuilder_get(last->bld, basename); if (e && git_tree_entry_type(e) != git_object__type_from_filemode(update->filemode)) { git__free(basename); - giterr_set(GITERR_TREE, "Cannot replace '%s' with '%s' at '%s'", + giterr_set(GITERR_TREE, "cannot replace '%s' with '%s' at '%s'", git_object_type2string(git_tree_entry_type(e)), git_object_type2string(git_object__type_from_filemode(update->filemode)), update->path); @@ -1257,7 +1257,7 @@ int git_tree_create_updated(git_oid *out, git_repository *repo, git_tree *baseli break; } default: - giterr_set(GITERR_TREE, "unkown action for update"); + giterr_set(GITERR_TREE, "unknown action for update"); error = -1; goto cleanup; } diff --git a/src/unix/map.c b/src/unix/map.c index c55ad1aa7..9d9b1fe38 100644 --- a/src/unix/map.c +++ b/src/unix/map.c @@ -52,7 +52,7 @@ int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offs out->data = mmap(NULL, len, mprot, mflag, fd, offset); if (!out->data || out->data == MAP_FAILED) { - giterr_set(GITERR_OS, "Failed to mmap. Could not write data"); + giterr_set(GITERR_OS, "failed to mmap. Could not write data"); return -1; } diff --git a/src/util.c b/src/util.c index 76ca711b2..a44f4c9ac 100644 --- a/src/util.c +++ b/src/util.c @@ -136,7 +136,7 @@ int git__strntol64(int64_t *result, const char *nptr, size_t nptr_len, const cha Return: if (ndig == 0) { - giterr_set(GITERR_INVALID, "Failed to convert string to long. Not a number"); + giterr_set(GITERR_INVALID, "failed to convert string to long: not a number"); return -1; } @@ -144,7 +144,7 @@ Return: *endptr = p; if (ovfl) { - giterr_set(GITERR_INVALID, "Failed to convert string to long. Overflow error"); + giterr_set(GITERR_INVALID, "failed to convert string to long: overflow error"); return -1; } @@ -169,7 +169,7 @@ int git__strntol32(int32_t *result, const char *nptr, size_t nptr_len, const cha tmp_int = tmp_long & 0xFFFFFFFF; if (tmp_int != tmp_long) { - giterr_set(GITERR_INVALID, "Failed to convert. '%s' is too large", nptr); + giterr_set(GITERR_INVALID, "failed to convert: '%s' is too large", nptr); return -1; } diff --git a/src/win32/dir.c b/src/win32/dir.c index c15757085..8a724a4e9 100644 --- a/src/win32/dir.c +++ b/src/win32/dir.c @@ -28,7 +28,7 @@ git__DIR *git__opendir(const char *dir) new->h = FindFirstFileW(filter_w, &new->f); if (new->h == INVALID_HANDLE_VALUE) { - giterr_set(GITERR_OS, "Could not open directory '%s'", dir); + giterr_set(GITERR_OS, "could not open directory '%s'", dir); git__free(new); return NULL; } @@ -53,7 +53,7 @@ int git__readdir_ext( else if (!FindNextFileW(d->h, &d->f)) { if (GetLastError() == ERROR_NO_MORE_FILES) return 0; - giterr_set(GITERR_OS, "Could not read from directory '%s'", d->dir); + giterr_set(GITERR_OS, "could not read from directory '%s'", d->dir); return -1; } @@ -98,7 +98,7 @@ void git__rewinddir(git__DIR *d) d->h = FindFirstFileW(filter_w, &d->f); if (d->h == INVALID_HANDLE_VALUE) - giterr_set(GITERR_OS, "Could not open directory '%s'", d->dir); + giterr_set(GITERR_OS, "could not open directory '%s'", d->dir); else d->first = 1; } diff --git a/src/win32/findfile.c b/src/win32/findfile.c index 58c22279e..1c768f7f4 100644 --- a/src/win32/findfile.c +++ b/src/win32/findfile.c @@ -38,7 +38,7 @@ static int win32_path_to_8(git_buf *dest, const wchar_t *src) git_win32_utf8_path utf8_path; if (git_win32_path_to_utf8(utf8_path, src) < 0) { - giterr_set(GITERR_OS, "Unable to convert path to UTF-8"); + giterr_set(GITERR_OS, "unable to convert path to UTF-8"); return -1; } diff --git a/src/win32/map.c b/src/win32/map.c index 03a3646a6..5fcc1085b 100644 --- a/src/win32/map.c +++ b/src/win32/map.c @@ -67,7 +67,7 @@ int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offs if (fh == INVALID_HANDLE_VALUE) { errno = EBADF; - giterr_set(GITERR_OS, "Failed to mmap. Invalid handle value"); + giterr_set(GITERR_OS, "failed to mmap. Invalid handle value"); return -1; } @@ -86,13 +86,13 @@ int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offs if (page_offset != 0) { /* offset must be multiple of the allocation granularity */ errno = EINVAL; - giterr_set(GITERR_OS, "Failed to mmap. Offset must be multiple of allocation granularity"); + giterr_set(GITERR_OS, "failed to mmap. Offset must be multiple of allocation granularity"); return -1; } out->fmh = CreateFileMapping(fh, NULL, fmap_prot, 0, 0, NULL); if (!out->fmh || out->fmh == INVALID_HANDLE_VALUE) { - giterr_set(GITERR_OS, "Failed to mmap. Invalid handle value"); + giterr_set(GITERR_OS, "failed to mmap. Invalid handle value"); out->fmh = NULL; return -1; } @@ -103,7 +103,7 @@ int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offs off_hi = (DWORD)(page_start >> 32); out->data = MapViewOfFile(out->fmh, view_prot, off_hi, off_low, len); if (!out->data) { - giterr_set(GITERR_OS, "Failed to mmap. No data written"); + giterr_set(GITERR_OS, "failed to mmap. No data written"); CloseHandle(out->fmh); out->fmh = NULL; return -1; @@ -121,7 +121,7 @@ int p_munmap(git_map *map) if (map->data) { if (!UnmapViewOfFile(map->data)) { - giterr_set(GITERR_OS, "Failed to munmap. Could not unmap view of file"); + giterr_set(GITERR_OS, "failed to munmap. Could not unmap view of file"); error = -1; } map->data = NULL; @@ -129,7 +129,7 @@ int p_munmap(git_map *map) if (map->fmh) { if (!CloseHandle(map->fmh)) { - giterr_set(GITERR_OS, "Failed to munmap. Could not close handle"); + giterr_set(GITERR_OS, "failed to munmap. Could not close handle"); error = -1; } map->fmh = NULL; diff --git a/src/win32/w32_crtdbg_stacktrace.c b/src/win32/w32_crtdbg_stacktrace.c index a778f4164..2dbdaf45b 100644 --- a/src/win32/w32_crtdbg_stacktrace.c +++ b/src/win32/w32_crtdbg_stacktrace.c @@ -253,11 +253,11 @@ int git_win32__crtdbg_stacktrace__dump( bool b_quiet = IS_BIT_SET(opt, GIT_WIN32__CRTDBG_STACKTRACE__QUIET); if (b_leaks_since_mark && b_leaks_total) { - giterr_set(GITERR_INVALID, "Cannot combine LEAKS_SINCE_MARK and LEAKS_TOTAL."); + giterr_set(GITERR_INVALID, "cannot combine LEAKS_SINCE_MARK and LEAKS_TOTAL."); return GIT_ERROR; } if (!b_set_mark && !b_leaks_since_mark && !b_leaks_total) { - giterr_set(GITERR_INVALID, "Nothing to do."); + giterr_set(GITERR_INVALID, "nothing to do."); return GIT_ERROR; } diff --git a/src/win32/w32_util.c b/src/win32/w32_util.c index 60311bb50..b7b1ffa10 100644 --- a/src/win32/w32_util.c +++ b/src/win32/w32_util.c @@ -68,7 +68,7 @@ int git_win32__set_hidden(const char *path, bool hidden) newattrs = attrs & ~FILE_ATTRIBUTE_HIDDEN; if (attrs != newattrs && !SetFileAttributesW(buf, newattrs)) { - giterr_set(GITERR_OS, "Failed to %s hidden bit for '%s'", + giterr_set(GITERR_OS, "failed to %s hidden bit for '%s'", hidden ? "set" : "unset", path); return -1; } diff --git a/src/win32/w32_util.h b/src/win32/w32_util.h index 784a7a04c..77973b502 100644 --- a/src/win32/w32_util.h +++ b/src/win32/w32_util.h @@ -174,7 +174,7 @@ GIT_INLINE(int) git_win32__file_attribute_to_stat( /* st_size gets the UTF-8 length of the target name, in bytes, * not counting the NULL terminator */ if ((st->st_size = git__utf16_to_8(NULL, 0, target)) < 0) { - giterr_set(GITERR_OS, "Could not convert reparse point name for '%ls'", path); + giterr_set(GITERR_OS, "could not convert reparse point name for '%ls'", path); return -1; } } diff --git a/src/zstream.c b/src/zstream.c index d949aa81a..141b49b27 100644 --- a/src/zstream.c +++ b/src/zstream.c @@ -23,7 +23,7 @@ static int zstream_seterr(git_zstream *zs) else if (zs->z.msg) giterr_set_str(GITERR_ZLIB, zs->z.msg); else - giterr_set(GITERR_ZLIB, "Unknown compression error"); + giterr_set(GITERR_ZLIB, "unknown compression error"); return -1; } From 8f0d5cdef9e2cb53c2f455d0a449f25c87647811 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 29 Dec 2016 12:55:49 +0000 Subject: [PATCH 014/366] tests: update error message checking --- tests/fetchhead/nonetwork.c | 4 ++-- tests/odb/backend/nobackend.c | 2 +- tests/refs/branches/upstream.c | 2 +- tests/refs/reflog/reflog.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/fetchhead/nonetwork.c b/tests/fetchhead/nonetwork.c index 3b750af5e..ea4b70e4a 100644 --- a/tests/fetchhead/nonetwork.c +++ b/tests/fetchhead/nonetwork.c @@ -293,7 +293,7 @@ void test_fetchhead_nonetwork__invalid_for_merge(void) cl_git_rewritefile("./test1/.git/FETCH_HEAD", "49322bb17d3acc9146f98c97d078513228bbf3c0\tinvalid-merge\t\n"); cl_git_fail(git_repository_fetchhead_foreach(g_repo, read_noop, NULL)); - cl_assert(git__prefixcmp(giterr_last()->message, "Invalid for-merge") == 0); + cl_assert(git__prefixcmp(giterr_last()->message, "invalid for-merge") == 0); } void test_fetchhead_nonetwork__invalid_description(void) @@ -304,7 +304,7 @@ void test_fetchhead_nonetwork__invalid_description(void) cl_git_rewritefile("./test1/.git/FETCH_HEAD", "49322bb17d3acc9146f98c97d078513228bbf3c0\tnot-for-merge\n"); cl_git_fail(git_repository_fetchhead_foreach(g_repo, read_noop, NULL)); - cl_assert(git__prefixcmp(giterr_last()->message, "Invalid description") == 0); + cl_assert(git__prefixcmp(giterr_last()->message, "invalid description") == 0); } static int assert_master_for_merge(const char *ref, const char *url, const git_oid *id, unsigned int is_merge, void *data) diff --git a/tests/odb/backend/nobackend.c b/tests/odb/backend/nobackend.c index 783641e8f..3c4f344b1 100644 --- a/tests/odb/backend/nobackend.c +++ b/tests/odb/backend/nobackend.c @@ -40,7 +40,7 @@ void test_odb_backend_nobackend__write_fails_gracefully(void) cl_git_fail(git_odb_write(&id, odb, "Hello world!\n", 13, GIT_OBJ_BLOB)); err = giterr_last(); - cl_assert_equal_s(err->message, "Cannot write object - unsupported in the loaded odb backends"); + cl_assert_equal_s(err->message, "cannot write object - unsupported in the loaded odb backends"); git_odb_free(odb); } diff --git a/tests/refs/branches/upstream.c b/tests/refs/branches/upstream.c index 8f2e7a2ca..82f5665d8 100644 --- a/tests/refs/branches/upstream.c +++ b/tests/refs/branches/upstream.c @@ -175,7 +175,7 @@ void test_refs_branches_upstream__no_fetch_refspec(void) cl_git_pass(git_reference_lookup(&branch, repo, "refs/heads/test")); cl_git_pass(git_reference_create(&ref, repo, "refs/remotes/matching/master", git_reference_target(branch), 1, "fetch")); cl_git_fail(git_branch_set_upstream(branch, "matching/master")); - cl_assert_equal_s("Could not determine remote for 'refs/remotes/matching/master'", + cl_assert_equal_s("could not determine remote for 'refs/remotes/matching/master'", giterr_last()->message); /* we can't set it automatically, so let's test the user setting it by hand */ diff --git a/tests/refs/reflog/reflog.c b/tests/refs/reflog/reflog.c index fdb15502c..9e46c8ae9 100644 --- a/tests/refs/reflog/reflog.c +++ b/tests/refs/reflog/reflog.c @@ -261,7 +261,7 @@ void test_refs_reflog_reflog__reading_a_reflog_with_invalid_format_returns_error error = giterr_last(); cl_assert(error != NULL); - cl_assert_equal_s("Unable to parse OID - contains invalid characters", error->message); + cl_assert_equal_s("unable to parse OID - contains invalid characters", error->message); git_reference_free(ref); git_buf_free(&logpath); From 832278bf36a382d51d8617d5575164a62ca26e6b Mon Sep 17 00:00:00 2001 From: Douglas Swanson Date: Thu, 29 Dec 2016 07:43:03 -0700 Subject: [PATCH 015/366] Fix issue #4046 Seg fault in config_files() --- examples/general.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/examples/general.c b/examples/general.c index 7c05d8712..cc0cf1b42 100644 --- a/examples/general.c +++ b/examples/general.c @@ -57,7 +57,7 @@ static void blob_parsing(git_repository *repo); static void revwalking(git_repository *repo); static void index_walking(git_repository *repo); static void reference_listing(git_repository *repo); -static void config_files(const char *repo_path); +static void config_files(const char *repo_path, git_repository *repo); /** * Almost all libgit2 functions return 0 on success or negative on error. @@ -115,7 +115,7 @@ int main (int argc, char** argv) revwalking(repo); index_walking(repo); reference_listing(repo); - config_files(repo_path); + config_files(repo_path, repo); /** * Finally, when you're done with the repository, you can free it as well. @@ -692,12 +692,13 @@ static void reference_listing(git_repository *repo) * * [config]: http://libgit2.github.com/libgit2/#HEAD/group/config */ -static void config_files(const char *repo_path) +static void config_files(const char *repo_path, git_repository* repo) { const char *email; char config_path[256]; int32_t j; git_config *cfg; + git_config *snap_cfg; printf("\n*Config Listing*\n"); @@ -710,6 +711,7 @@ static void config_files(const char *repo_path) git_config_get_int32(&j, cfg, "help.autocorrect"); printf("Autocorrect: %d\n", j); - git_config_get_string(&email, cfg, "user.email"); + check_error(git_repository_config_snapshot(&snap_cfg, repo), "config snapshot"); + git_config_get_string(&email, snap_cfg, "user.email"); printf("Email: %s\n", email); } From c7a1535f3202ccc38bbdf9e5084c1d6e589e2dd0 Mon Sep 17 00:00:00 2001 From: Chris Hescock Date: Thu, 29 Dec 2016 11:47:52 -0500 Subject: [PATCH 016/366] Extend packfile in increments of page_size. This improves performance by reducing the number of I/O operations. --- src/indexer.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/indexer.c b/src/indexer.c index a3a866989..67fef1cbc 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -477,13 +477,29 @@ static int write_at(git_indexer *idx, const void *data, git_off_t offset, size_t static int append_to_pack(git_indexer *idx, const void *data, size_t size) { + git_off_t new_size; + size_t mmap_alignment; + size_t page_offset; + git_off_t page_start; git_off_t current_size = idx->pack->mwf.size; int fd = idx->pack->mwf.fd; + int error; if (!size) return 0; - if (p_lseek(fd, current_size + size - 1, SEEK_SET) < 0 || + if ((error = git__mmap_alignment(&mmap_alignment)) < 0) + return error; + + /* Write a single byte to force the file system to allocate space now or + * report an error, since we can't report errors when writing using mmap. + * Round the size up to the nearest page so that we only need to perform file + * I/O when we add a page, instead of whenever we write even a single byte. */ + new_size = current_size + size; + page_offset = new_size % mmap_alignment; + page_start = new_size - page_offset; + + if (p_lseek(fd, page_start + mmap_alignment - 1, SEEK_SET) < 0 || p_write(idx->pack->mwf.fd, data, 1) < 0) { giterr_set(GITERR_OS, "cannot extend packfile '%s'", idx->pack->pack_name); return -1; @@ -1041,6 +1057,13 @@ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats) goto on_error; git_mwindow_free_all(&idx->pack->mwf); + + /* Truncate file to undo rounding up to next page_size in append_to_pack */ + if (p_ftruncate(idx->pack->mwf.fd, idx->pack->mwf.size) < 0) { + giterr_set(GITERR_OS, "failed to truncate pack file '%s'", idx->pack->pack_name); + return -1; + } + /* We need to close the descriptor here so Windows doesn't choke on commit_at */ if (p_close(idx->pack->mwf.fd) < 0) { giterr_set(GITERR_OS, "failed to close packfile"); From 5f959dca0d7d7d921ccf2948e0745659f6055148 Mon Sep 17 00:00:00 2001 From: John Fultz Date: Thu, 29 Dec 2016 19:26:50 -0600 Subject: [PATCH 017/366] Fix handling of GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH flag. git_checkout_tree() sets up its working directory iterator to respect the pathlist if GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH is present, which is great. What's not so great is that this iterator is then used side-by-side with an iterator created by git_checkout_iterator(), which did not set up its pathlist appropriately (although the iterator mirrors all other iterator options). This could cause git_checkout_tree() to delete working tree files which were not specified in the pathlist when GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH was used, as the unsynchronized iterators causes git_checkout_tree() to think that files have been deleted between the two trees. Oops. And added a test which fails without this fix (specifically, the final check for "testrepo/README" to still be present fails). --- src/checkout.c | 4 ++++ tests/checkout/tree.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/src/checkout.c b/src/checkout.c index 62950913e..578695a37 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -2553,6 +2553,10 @@ int git_checkout_iterator( GIT_ITERATOR_IGNORE_CASE : GIT_ITERATOR_DONT_IGNORE_CASE; baseline_opts.start = data.pfx; baseline_opts.end = data.pfx; + if (opts && (opts->checkout_strategy & GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH)) { + baseline_opts.pathlist.count = opts->paths.count; + baseline_opts.pathlist.strings = opts->paths.strings; + } if (data.opts.baseline_index) { if ((error = git_iterator_for_index( diff --git a/tests/checkout/tree.c b/tests/checkout/tree.c index 4a0314a9e..c9581fdc5 100644 --- a/tests/checkout/tree.c +++ b/tests/checkout/tree.c @@ -422,6 +422,44 @@ void test_checkout_tree__can_checkout_with_pattern(void) cl_assert(git_path_exists("testrepo/new.txt")); } +void test_checkout_tree__pathlist_checkout_ignores_non_matches(void) +{ + char *entries[] = { "branch_file.txt", "link_to_new.txt" }; + + /* reset to beginning of history (i.e. just a README file) */ + + g_opts.checkout_strategy = + GIT_CHECKOUT_FORCE | GIT_CHECKOUT_REMOVE_UNTRACKED; + + cl_git_pass(git_revparse_single(&g_object, g_repo, "refs/heads/master")); + + cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts)); + cl_git_pass(git_repository_set_head(g_repo, "refs/heads/master")); + + cl_assert(git_path_exists("testrepo/README")); + cl_assert(git_path_exists("testrepo/branch_file.txt")); + cl_assert(git_path_exists("testrepo/link_to_new.txt")); + cl_assert(git_path_exists("testrepo/new.txt")); + + cl_git_pass(git_revparse_single(&g_object, g_repo, "8496071c1b46c854b31185ea97743be6a8774479")); + + g_opts.checkout_strategy = + GIT_CHECKOUT_FORCE | GIT_CHECKOUT_DISABLE_PATHSPEC_MATCH; + g_opts.paths.strings = entries; + g_opts.paths.count = 2; + + cl_git_pass(git_checkout_tree(g_repo, g_object, &g_opts)); + + cl_assert(git_path_exists("testrepo/README")); + cl_assert(!git_path_exists("testrepo/branch_file.txt")); + cl_assert(!git_path_exists("testrepo/link_to_new.txt")); + cl_assert(git_path_exists("testrepo/new.txt")); + + git_object_free(g_object); + g_object = NULL; + +} + void test_checkout_tree__can_disable_pattern_match(void) { char *entries[] = { "b*.txt" }; From e56e4c76b930e600419af24a3433f1517e1a6e0f Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Fri, 30 Dec 2016 17:59:47 -0800 Subject: [PATCH 018/366] CMakeLists: Move `http-parser` block down by `zlib`, update error message --- CMakeLists.txt | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8cc43c6ea..4bfd1b499 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -235,19 +235,6 @@ IF (WIN32 AND EMBED_SSH_PATH) ADD_DEFINITIONS(-DGIT_SSH) ENDIF() - -FIND_PACKAGE(HTTP_Parser) -IF (HTTP_PARSER_FOUND AND HTTP_PARSER_VERSION_MAJOR EQUAL 2) - INCLUDE_DIRECTORIES(${HTTP_PARSER_INCLUDE_DIRS}) - LINK_LIBRARIES(${HTTP_PARSER_LIBRARIES}) - LIST(APPEND LIBGIT2_PC_LIBS "-lhttp_parser") -ELSE() - MESSAGE(STATUS "http-parser was not found or is too old; using bundled 3rd-party sources.") - INCLUDE_DIRECTORIES(deps/http-parser) - FILE(GLOB SRC_HTTP deps/http-parser/*.c deps/http-parser/*.h) -ENDIF() - - IF (WIN32 AND WINHTTP) ADD_DEFINITIONS(-DGIT_WINHTTP) @@ -332,6 +319,18 @@ IF(WIN32 OR AMIGA OR CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)") SET(SRC_REGEX deps/regex/regex.c) ENDIF() +# Optional external dependency: http-parser +FIND_PACKAGE(HTTP_Parser) +IF (HTTP_PARSER_FOUND AND HTTP_PARSER_VERSION_MAJOR EQUAL 2) + INCLUDE_DIRECTORIES(${HTTP_PARSER_INCLUDE_DIRS}) + LINK_LIBRARIES(${HTTP_PARSER_LIBRARIES}) + LIST(APPEND LIBGIT2_PC_LIBS "-lhttp_parser") +ELSE() + MESSAGE(STATUS "http-parser version 2 was not found; using bundled 3rd-party sources.") + INCLUDE_DIRECTORIES(deps/http-parser) + FILE(GLOB SRC_HTTP deps/http-parser/*.c deps/http-parser/*.h) +ENDIF() + # Optional external dependency: zlib FIND_PACKAGE(ZLIB) IF (ZLIB_FOUND) From db535d0a7dfa3e5c2ded4a408234623b0241de00 Mon Sep 17 00:00:00 2001 From: lhchavez Date: Sun, 1 Jan 2017 12:45:02 -0800 Subject: [PATCH 019/366] Delete temporary packfile in indexer This change deletes the temporary packfile that the indexer creates to avoid littering the pack/ directory with garbage. --- src/indexer.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/indexer.c b/src/indexer.c index a3a866989..27f49473a 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -151,6 +151,12 @@ cleanup: if (fd != -1) p_close(fd); + if (git_buf_is_allocated(&tmp_path)) + (void)p_unlink(git_buf_cstr(&tmp_path)); + + if (idx->pack != NULL) + (void)p_unlink(idx->pack->pack_name); + git_buf_free(&path); git_buf_free(&tmp_path); git__free(idx); @@ -1084,6 +1090,9 @@ void git_indexer_free(git_indexer *idx) git_vector_free_deep(&idx->deltas); + /* Try to delete the temporary file in case it was not committed. */ + (void)p_unlink(idx->pack->pack_name); + if (!git_mutex_lock(&git__mwindow_mutex)) { git_packfile_free(idx->pack); git_mutex_unlock(&git__mwindow_mutex); From 19ed4d0ca3fdd2f46e1391597aa2b70e4f330c6f Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Sun, 1 Jan 2017 22:19:23 +0000 Subject: [PATCH 020/366] merge: set default rename threshold When `GIT_MERGE_FIND_RENAMES` is set, provide a default for `rename_threshold` when it is unset. --- include/git2/merge.h | 3 ++- src/merge.c | 10 +++++----- tests/merge/trees/renames.c | 2 ++ 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/include/git2/merge.h b/include/git2/merge.h index c6f6cba6c..94ac8b5c5 100644 --- a/include/git2/merge.h +++ b/include/git2/merge.h @@ -290,7 +290,8 @@ typedef struct { } git_merge_options; #define GIT_MERGE_OPTIONS_VERSION 1 -#define GIT_MERGE_OPTIONS_INIT {GIT_MERGE_OPTIONS_VERSION} +#define GIT_MERGE_OPTIONS_INIT { \ + GIT_MERGE_OPTIONS_VERSION, GIT_MERGE_FIND_RENAMES } /** * Initializes a `git_merge_options` with default values. Equivalent to diff --git a/src/merge.c b/src/merge.c index 1142917bd..c75cab635 100644 --- a/src/merge.c +++ b/src/merge.c @@ -1713,16 +1713,16 @@ static int merge_normalize_opts( if ((error = git_repository_config__weakptr(&cfg, repo)) < 0) return error; - if (given != NULL) + if (given != NULL) { memcpy(opts, given, sizeof(git_merge_options)); - else { + } else { git_merge_options init = GIT_MERGE_OPTIONS_INIT; memcpy(opts, &init, sizeof(init)); - - opts->flags = GIT_MERGE_FIND_RENAMES; - opts->rename_threshold = GIT_MERGE_DEFAULT_RENAME_THRESHOLD; } + if ((opts->flags & GIT_MERGE_FIND_RENAMES) && !opts->rename_threshold) + opts->rename_threshold = GIT_MERGE_DEFAULT_RENAME_THRESHOLD; + if (given && given->default_driver) { opts->default_driver = git__strdup(given->default_driver); GITERR_CHECK_ALLOC(opts->default_driver); diff --git a/tests/merge/trees/renames.c b/tests/merge/trees/renames.c index d7721c894..6f5c36b0a 100644 --- a/tests/merge/trees/renames.c +++ b/tests/merge/trees/renames.c @@ -242,6 +242,8 @@ void test_merge_trees_renames__no_rename_index(void) { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 3, "7-both-renamed.txt" }, }; + opts.flags &= ~GIT_MERGE_FIND_RENAMES; + cl_git_pass(merge_trees_from_branches(&index, repo, BRANCH_RENAME_OURS, BRANCH_RENAME_THEIRS, &opts)); From def644e48a3cd4afd0cee975d3214eeeb3671c99 Mon Sep 17 00:00:00 2001 From: lhchavez Date: Sun, 1 Jan 2017 17:35:29 -0800 Subject: [PATCH 021/366] Add a test --- tests/pack/indexer.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/tests/pack/indexer.c b/tests/pack/indexer.c index 49a106d98..15a9017f1 100644 --- a/tests/pack/indexer.c +++ b/tests/pack/indexer.c @@ -125,3 +125,43 @@ void test_pack_indexer__fix_thin(void) git_indexer_free(idx); } } + +static int find_tmp_file_recurs(void *opaque, git_buf *path) +{ + int error = 0; + git_buf *first_tmp_file = opaque; + struct stat st; + + if ((error = p_lstat_posixly(path->ptr, &st)) < 0) + return error; + + if (S_ISDIR(st.st_mode)) + return git_path_direach(path, 0, find_tmp_file_recurs, opaque); + + /* This is the template that's used in git_futils_mktmp. */ + if (strstr(git_buf_cstr(path), "_git2_") != NULL) + return git_buf_sets(first_tmp_file, git_buf_cstr(path)); + + return 0; +} + +void test_pack_indexer__no_tmp_files(void) +{ + git_indexer *idx = NULL; + git_buf path = GIT_BUF_INIT; + git_buf first_tmp_file = GIT_BUF_INIT; + + /* Precondition: there are no temporary files. */ + cl_git_pass(git_buf_sets(&path, clar_sandbox_path())); + cl_git_pass(find_tmp_file_recurs(&first_tmp_file, &path)); + if (git_buf_is_allocated(&first_tmp_file)) { + cl_warning("Found a temporary file before running the test"); + cl_skip(); + } + + cl_git_pass(git_indexer_new(&idx, ".", 0, NULL, NULL, NULL)); + git_indexer_free(idx); + + cl_git_pass(find_tmp_file_recurs(&first_tmp_file, &path)); + cl_check(!git_buf_is_allocated(&first_tmp_file)); +} From 31c7829954c376b419f5ab318c4a00628a0002d3 Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Tue, 3 Jan 2017 10:11:52 +0000 Subject: [PATCH 022/366] mention field addition in breaking API changes --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8544ac451..69ebd3a2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -150,7 +150,8 @@ v0.25 If this is `NULL`, then it will not be called and the `exists` function will be used instead. -* `git_remote_connect()` now accepts proxy options. +* `git_remote_connect()` now accepts `git_proxy_options` argument, and + `git_fetch_options` and `git_push_options` each have a `proxy_opts` field. v0.24 ------- From d8f984bc4980a491ffc61dcfdd57bed27c34ff0d Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Tue, 3 Jan 2017 10:54:24 +0000 Subject: [PATCH 023/366] move git_merge_options changes to correct location --- CHANGELOG.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 69ebd3a2b..3a8db068f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -153,6 +153,10 @@ v0.25 * `git_remote_connect()` now accepts `git_proxy_options` argument, and `git_fetch_options` and `git_push_options` each have a `proxy_opts` field. +* `git_merge_options` now provides a `default_driver` that can be used + to provide the name of a merge driver to be used to handle files changed + during a merge. + v0.24 ------- @@ -228,10 +232,6 @@ v0.24 ### Breaking API changes -* `git_merge_options` now provides a `default_driver` that can be used - to provide the name of a merge driver to be used to handle files changed - during a merge. - * The `git_merge_tree_flag_t` is now `git_merge_flag_t`. Subsequently, its members are no longer prefixed with `GIT_MERGE_TREE_FLAG` but are now prefixed with `GIT_MERGE_FLAG`, and the `tree_flags` field of the From a7ff6e5e5e2715ecccdb217f2018dc2567e1eebd Mon Sep 17 00:00:00 2001 From: lhchavez Date: Tue, 3 Jan 2017 18:24:51 -0800 Subject: [PATCH 024/366] Fix the memory leak --- tests/pack/indexer.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/pack/indexer.c b/tests/pack/indexer.c index 15a9017f1..2c9724605 100644 --- a/tests/pack/indexer.c +++ b/tests/pack/indexer.c @@ -154,7 +154,9 @@ void test_pack_indexer__no_tmp_files(void) /* Precondition: there are no temporary files. */ cl_git_pass(git_buf_sets(&path, clar_sandbox_path())); cl_git_pass(find_tmp_file_recurs(&first_tmp_file, &path)); + git_buf_free(&path); if (git_buf_is_allocated(&first_tmp_file)) { + git_buf_free(&first_tmp_file); cl_warning("Found a temporary file before running the test"); cl_skip(); } @@ -162,6 +164,12 @@ void test_pack_indexer__no_tmp_files(void) cl_git_pass(git_indexer_new(&idx, ".", 0, NULL, NULL, NULL)); git_indexer_free(idx); + cl_git_pass(git_buf_sets(&path, clar_sandbox_path())); cl_git_pass(find_tmp_file_recurs(&first_tmp_file, &path)); - cl_check(!git_buf_is_allocated(&first_tmp_file)); + git_buf_free(&path); + if (git_buf_is_allocated(&first_tmp_file)) { + cl_warning(git_buf_cstr(&first_tmp_file)); + git_buf_free(&first_tmp_file); + cl_fail("Found a temporary file"); + } } From 96df833b63f37c21240094aa740f05600ef9c2b9 Mon Sep 17 00:00:00 2001 From: lhchavez Date: Tue, 3 Jan 2017 19:15:09 -0800 Subject: [PATCH 025/366] Close the file before unlinking I forgot that Windows chokes while trying to delete open files. --- src/indexer.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/indexer.c b/src/indexer.c index 27f49473a..93153621a 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -1091,6 +1091,12 @@ void git_indexer_free(git_indexer *idx) git_vector_free_deep(&idx->deltas); /* Try to delete the temporary file in case it was not committed. */ + git_mwindow_free_all(&idx->pack->mwf); + /* We need to close the descriptor here so Windows doesn't choke on unlink */ + if (idx->pack->mwf.fd != -1) { + (void)p_close(idx->pack->mwf.fd); + idx->pack->mwf.fd = -1; + } (void)p_unlink(idx->pack->pack_name); if (!git_mutex_lock(&git__mwindow_mutex)) { From 3fdba15c2f3fd8577dff6cbc61073b723136af4d Mon Sep 17 00:00:00 2001 From: "Force.Charlie-I" Date: Mon, 9 Jan 2017 14:09:57 +0800 Subject: [PATCH 026/366] fix examples/network/clone.c: heap-buffer-overflow Format of a length of string to the correct format is:%.*s --- examples/network/clone.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/network/clone.c b/examples/network/clone.c index caf41cca8..540000bfd 100644 --- a/examples/network/clone.c +++ b/examples/network/clone.c @@ -50,7 +50,7 @@ static int sideband_progress(const char *str, int len, void *payload) { (void)payload; // unused - printf("remote: %*s", len, str); + printf("remote: %.*s", len, str); fflush(stdout); return 0; } From 8572e2252b9013cef7513f4e55523603c4d95ff6 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Thu, 12 Jan 2017 22:00:53 +0100 Subject: [PATCH 027/366] examples: general: clean up committer/author variables --- examples/general.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/general.c b/examples/general.c index cc0cf1b42..d59f67f5e 100644 --- a/examples/general.c +++ b/examples/general.c @@ -264,7 +264,7 @@ static void commit_writing(git_repository *repo) git_oid tree_id, parent_id, commit_id; git_tree *tree; git_commit *parent; - const git_signature *author, *cmtter; + git_signature *author, *committer; char oid_hex[GIT_OID_HEXSZ+1] = { 0 }; printf("\n*Commit Writing*\n"); @@ -276,9 +276,9 @@ static void commit_writing(git_repository *repo) * `user.email` configuration options. See the `config` section of this * example file to see how to access config values. */ - git_signature_new((git_signature **)&author, + git_signature_new(&author, "Scott Chacon", "schacon@gmail.com", 123456789, 60); - git_signature_new((git_signature **)&cmtter, + git_signature_new(&committer, "Scott A Chacon", "scott@github.com", 987654321, 90); /** @@ -301,7 +301,7 @@ static void commit_writing(git_repository *repo) repo, NULL, /* do not update the HEAD */ author, - cmtter, + committer, NULL, /* use default message encoding */ "example commit", tree, From 5aa101078eec51a99fbbf4015162da7e254bb320 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Thu, 12 Jan 2017 22:01:23 +0100 Subject: [PATCH 028/366] examples: general: narrow down scope of loop variables --- examples/general.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/examples/general.c b/examples/general.c index d59f67f5e..aa54074a7 100644 --- a/examples/general.c +++ b/examples/general.c @@ -644,10 +644,7 @@ static void index_walking(git_repository *repo) static void reference_listing(git_repository *repo) { git_strarray ref_list; - const char *refname; - git_reference *ref; unsigned i; - char oid_hex[GIT_OID_HEXSZ+1]; printf("\n*Reference Listing*\n"); @@ -662,7 +659,10 @@ static void reference_listing(git_repository *repo) git_reference_list(&ref_list, repo); for (i = 0; i < ref_list.count; ++i) { - memset(oid_hex, 0, sizeof(oid_hex)); + git_reference *ref; + char oid_hex[GIT_OID_HEXSZ+1] = GIT_OID_HEX_ZERO; + const char *refname; + refname = ref_list.strings[i]; git_reference_lookup(&ref, repo, refname); @@ -679,6 +679,8 @@ static void reference_listing(git_repository *repo) fprintf(stderr, "Unexpected reference type\n"); exit(1); } + + git_reference_free(ref); } git_strarray_free(&ref_list); From ed2b1c7e75ab9d8aa4b23eec81bb023bcfdabbda Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Thu, 12 Jan 2017 22:01:45 +0100 Subject: [PATCH 029/366] examples: general: display config only if it was found --- examples/general.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/general.c b/examples/general.c index aa54074a7..ecb7c212f 100644 --- a/examples/general.c +++ b/examples/general.c @@ -698,7 +698,7 @@ static void config_files(const char *repo_path, git_repository* repo) { const char *email; char config_path[256]; - int32_t j; + int32_t autocorrect; git_config *cfg; git_config *snap_cfg; @@ -710,8 +710,8 @@ static void config_files(const char *repo_path, git_repository* repo) sprintf(config_path, "%s/config", repo_path); check_error(git_config_open_ondisk(&cfg, config_path), "opening config"); - git_config_get_int32(&j, cfg, "help.autocorrect"); - printf("Autocorrect: %d\n", j); + if (git_config_get_int32(&autocorrect, cfg, "help.autocorrect") == 0) + printf("Autocorrect: %d\n", autocorrect); check_error(git_repository_config_snapshot(&snap_cfg, repo), "config snapshot"); git_config_get_string(&email, snap_cfg, "user.email"); From f9ea8c6a142d5c9c3248123acab5ea3950dfc049 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Thu, 12 Jan 2017 22:02:14 +0100 Subject: [PATCH 030/366] examples: general: fix memory leaks --- examples/general.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/examples/general.c b/examples/general.c index ecb7c212f..ff984a36c 100644 --- a/examples/general.c +++ b/examples/general.c @@ -247,6 +247,11 @@ static void object_database(git_repository *repo, git_oid *oid) */ git_oid_fmt(oid_hex, oid); printf("Written Object: %s\n", oid_hex); + + /** + * Free the object database after usage. + */ + git_odb_free(odb); } /** @@ -312,6 +317,14 @@ static void commit_writing(git_repository *repo) */ git_oid_fmt(oid_hex, &commit_id); printf("New Commit: %s\n", oid_hex); + + /** + * Free all objects used in the meanwhile. + */ + git_tree_free(tree); + git_commit_free(parent); + git_signature_free(author); + git_signature_free(committer); } /** @@ -431,7 +444,11 @@ static void tag_parsing(git_repository *repo) printf("Tag Name: %s\nTag Type: %s\nTag Message: %s\n", name, git_object_type2string(type), message); + /** + * Free both the commit and tag after usage. + */ git_commit_free(commit); + git_tag_free(tag); } /** @@ -485,9 +502,10 @@ static void tree_parsing(git_repository *repo) git_tree_entry_to_object(&obj, repo, entry); /* blob */ /** - * Remember to close the looked-up object once you are done using it + * Remember to close the looked-up object and tree once you are done using it */ git_object_free(obj); + git_tree_free(tree); } /** @@ -522,6 +540,11 @@ static void blob_parsing(git_repository *repo) * */ printf("Blob Size: %ld\n", (long)git_blob_rawsize(blob)); /* 8 */ git_blob_rawcontent(blob); /* "content" */ + + /** + * Free the blob after usage. + */ + git_blob_free(blob); } /** @@ -716,4 +739,10 @@ static void config_files(const char *repo_path, git_repository* repo) check_error(git_repository_config_snapshot(&snap_cfg, repo), "config snapshot"); git_config_get_string(&email, snap_cfg, "user.email"); printf("Email: %s\n", email); + + /** + * Remember to free the configurations after usage. + */ + git_config_free(cfg); + git_config_free(snap_cfg); } From 8a349bf2a1e7257a4f35599b3613d7953289dc88 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Mon, 26 Dec 2016 14:47:55 +0100 Subject: [PATCH 031/366] ignore: there must be a repository Otherwise we'll NULL-dereference in git_attr_cache__init --- src/ignore.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ignore.c b/src/ignore.c index d1a6c5550..cc9e08e35 100644 --- a/src/ignore.c +++ b/src/ignore.c @@ -278,7 +278,7 @@ int git_ignore__for_path( int error = 0; const char *workdir = git_repository_workdir(repo); - assert(ignores && path); + assert(repo && ignores && path); memset(ignores, 0, sizeof(*ignores)); ignores->repo = repo; @@ -503,9 +503,9 @@ int git_ignore_path_is_ignored( unsigned int i; git_attr_file *file; - assert(ignored && pathname); + assert(repo && ignored && pathname); - workdir = repo ? git_repository_workdir(repo) : NULL; + workdir = git_repository_workdir(repo); memset(&path, 0, sizeof(path)); memset(&ignores, 0, sizeof(ignores)); From b0014063b229132b358e56b40892807d1ee5df9d Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Mon, 26 Dec 2016 22:13:35 +0100 Subject: [PATCH 032/366] patch: memory leak of patch.base.diff_opts.new|old_prefix --- src/patch_generate.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/patch_generate.c b/src/patch_generate.c index 3559cc2b8..ab68f5801 100644 --- a/src/patch_generate.c +++ b/src/patch_generate.c @@ -451,8 +451,10 @@ int git_diff_foreach( if (binary_cb || hunk_cb || data_cb) { if ((error = patch_generated_init(&patch, diff, idx)) != 0 || - (error = patch_generated_load(&patch, &xo.output)) != 0) + (error = patch_generated_load(&patch, &xo.output)) != 0) { + git_patch_free(&patch.base); return error; + } } if ((error = patch_generated_invoke_file_callback(&patch, &xo.output)) == 0) { From 49be45a18941cfe2e98fa3312e52c7ef4119fdcb Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Mon, 26 Dec 2016 22:15:31 +0100 Subject: [PATCH 033/366] pack: report revwalk error --- src/pack-objects.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pack-objects.c b/src/pack-objects.c index 6dbb6cf6c..2e5de98ab 100644 --- a/src/pack-objects.c +++ b/src/pack-objects.c @@ -1738,7 +1738,7 @@ int git_packbuilder_insert_walk(git_packbuilder *pb, git_revwalk *walk) if (error == GIT_ITEROVER) error = 0; - return 0; + return error; } int git_packbuilder_set_callbacks(git_packbuilder *pb, git_packbuilder_progress progress_cb, void *progress_cb_payload) From 07bb8078cbea77e3d85bf087e2510c2e23d8fa29 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Sat, 14 Jan 2017 16:01:53 +0000 Subject: [PATCH 034/366] CHANGELOG: update `GIT_MERGE_OPTIONS_INIT` changes --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8544ac451..9e60424ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ v0.25 + 1 ### Changes or improvements +* `GIT_MERGE_OPTIONS_INIT` now includes a setting to perform rename detection. + This aligns this structure with the default by `git_merge` and + `git_merge_trees` when `NULL` was provided for the options. + ### API additions ### API removals From f5586f5c73ac162393df10feec0117f59bbd1409 Mon Sep 17 00:00:00 2001 From: lhchavez Date: Sat, 14 Jan 2017 16:37:00 +0000 Subject: [PATCH 035/366] Addressed review feedback --- src/indexer.c | 10 +++++----- tests/pack/indexer.c | 13 +++---------- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/src/indexer.c b/src/indexer.c index 93153621a..3d1c81c86 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -151,11 +151,11 @@ cleanup: if (fd != -1) p_close(fd); - if (git_buf_is_allocated(&tmp_path)) - (void)p_unlink(git_buf_cstr(&tmp_path)); + if (git_buf_len(&tmp_path) > 0) + p_unlink(git_buf_cstr(&tmp_path)); if (idx->pack != NULL) - (void)p_unlink(idx->pack->pack_name); + p_unlink(idx->pack->pack_name); git_buf_free(&path); git_buf_free(&tmp_path); @@ -1094,10 +1094,10 @@ void git_indexer_free(git_indexer *idx) git_mwindow_free_all(&idx->pack->mwf); /* We need to close the descriptor here so Windows doesn't choke on unlink */ if (idx->pack->mwf.fd != -1) { - (void)p_close(idx->pack->mwf.fd); + p_close(idx->pack->mwf.fd); idx->pack->mwf.fd = -1; } - (void)p_unlink(idx->pack->pack_name); + p_unlink(idx->pack->pack_name); if (!git_mutex_lock(&git__mwindow_mutex)) { git_packfile_free(idx->pack); diff --git a/tests/pack/indexer.c b/tests/pack/indexer.c index 2c9724605..1e514b2d6 100644 --- a/tests/pack/indexer.c +++ b/tests/pack/indexer.c @@ -155,11 +155,7 @@ void test_pack_indexer__no_tmp_files(void) cl_git_pass(git_buf_sets(&path, clar_sandbox_path())); cl_git_pass(find_tmp_file_recurs(&first_tmp_file, &path)); git_buf_free(&path); - if (git_buf_is_allocated(&first_tmp_file)) { - git_buf_free(&first_tmp_file); - cl_warning("Found a temporary file before running the test"); - cl_skip(); - } + cl_assert(git_buf_len(&first_tmp_file) == 0); cl_git_pass(git_indexer_new(&idx, ".", 0, NULL, NULL, NULL)); git_indexer_free(idx); @@ -167,9 +163,6 @@ void test_pack_indexer__no_tmp_files(void) cl_git_pass(git_buf_sets(&path, clar_sandbox_path())); cl_git_pass(find_tmp_file_recurs(&first_tmp_file, &path)); git_buf_free(&path); - if (git_buf_is_allocated(&first_tmp_file)) { - cl_warning(git_buf_cstr(&first_tmp_file)); - git_buf_free(&first_tmp_file); - cl_fail("Found a temporary file"); - } + cl_assert(git_buf_len(&first_tmp_file) == 0); + git_buf_free(&first_tmp_file); } From 4e4a1460ebf6e2ed53c23ddf641307346aaa6db2 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 30 Dec 2016 12:13:34 -0500 Subject: [PATCH 036/366] WinHTTP: support best auth mechanism For username/password credentials, support NTLM or Basic (in that order of priority). Use the WinHTTP built-in authentication support for both, and maintain a bitfield of the supported mechanisms from the response. --- src/transports/winhttp.c | 131 +++++++++++++++++++-------------------- 1 file changed, 64 insertions(+), 67 deletions(-) diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c index 051340d87..79b3ac6b4 100644 --- a/src/transports/winhttp.c +++ b/src/transports/winhttp.c @@ -68,7 +68,8 @@ static const IID IID_IInternetSecurityManager_mingw = typedef enum { GIT_WINHTTP_AUTH_BASIC = 1, - GIT_WINHTTP_AUTH_NEGOTIATE = 2, + GIT_WINHTTP_AUTH_NTLM = 2, + GIT_WINHTTP_AUTH_NEGOTIATE = 4, } winhttp_authmechanism_t; typedef struct { @@ -95,79 +96,66 @@ typedef struct { git_cred *cred; git_cred *url_cred; git_cred *proxy_cred; - int auth_mechanism; + int auth_mechanisms; HINTERNET session; HINTERNET connection; } winhttp_subtransport; -static int apply_basic_credential_proxy(HINTERNET request, git_cred *cred) +static int _apply_userpass_credential(HINTERNET request, DWORD target, DWORD scheme, git_cred *cred) { git_cred_userpass_plaintext *c = (git_cred_userpass_plaintext *)cred; wchar_t *user, *pass; - int error; + int user_len = 0, pass_len = 0, error = 0; - if ((error = git__utf8_to_16_alloc(&user, c->username)) < 0) - return error; + if ((error = user_len = git__utf8_to_16_alloc(&user, c->username)) < 0) + goto done; - if ((error = git__utf8_to_16_alloc(&pass, c->password)) < 0) - return error; + if ((error = pass_len = git__utf8_to_16_alloc(&pass, c->password)) < 0) + goto done; - if (!WinHttpSetCredentials(request, WINHTTP_AUTH_TARGET_PROXY, WINHTTP_AUTH_SCHEME_BASIC, - user, pass, NULL)) { - giterr_set(GITERR_OS, "failed to set proxy auth"); + if (!WinHttpSetCredentials(request, target, scheme, user, pass, NULL)) { + giterr_set(GITERR_OS, "failed to set credentials"); error = -1; } +done: + if (user_len > 0) + git__memzero(user, user_len * sizeof(wchar_t)); + + if (pass_len > 0) + git__memzero(pass, pass_len * sizeof(wchar_t)); + git__free(user); git__free(pass); return error; } -static int apply_basic_credential(HINTERNET request, git_cred *cred) +static int apply_userpass_credential_proxy(HINTERNET request, git_cred *cred) { - git_cred_userpass_plaintext *c = (git_cred_userpass_plaintext *)cred; - git_buf buf = GIT_BUF_INIT, raw = GIT_BUF_INIT; - wchar_t *wide = NULL; - int error = -1, wide_len; - - git_buf_printf(&raw, "%s:%s", c->username, c->password); - - if (git_buf_oom(&raw) || - git_buf_puts(&buf, "Authorization: Basic ") < 0 || - git_buf_encode_base64(&buf, git_buf_cstr(&raw), raw.size) < 0) - goto on_error; - - if ((wide_len = git__utf8_to_16_alloc(&wide, git_buf_cstr(&buf))) < 0) { - giterr_set(GITERR_OS, "failed to convert string to wide form"); - goto on_error; - } - - if (!WinHttpAddRequestHeaders(request, wide, (ULONG) -1L, WINHTTP_ADDREQ_FLAG_ADD)) { - giterr_set(GITERR_OS, "failed to add a header to the request"); - goto on_error; - } - - error = 0; - -on_error: - /* We were dealing with plaintext passwords, so clean up after ourselves a bit. */ - if (wide) - memset(wide, 0x0, wide_len * sizeof(wchar_t)); - - if (buf.size) - memset(buf.ptr, 0x0, buf.size); - - if (raw.size) - memset(raw.ptr, 0x0, raw.size); - - git__free(wide); - git_buf_free(&buf); - git_buf_free(&raw); - return error; + return _apply_userpass_credential(request, WINHTTP_AUTH_TARGET_PROXY, + WINHTTP_AUTH_SCHEME_BASIC, cred); } -static int apply_default_credentials(HINTERNET request) +static int apply_userpass_credential(HINTERNET request, int mechanisms, git_cred *cred) +{ + DWORD native_scheme; + + if ((mechanisms & GIT_WINHTTP_AUTH_NTLM) || + (mechanisms & GIT_WINHTTP_AUTH_NEGOTIATE)) { + native_scheme = WINHTTP_AUTH_SCHEME_NTLM; + } else if (mechanisms & GIT_WINHTTP_AUTH_BASIC) { + native_scheme = WINHTTP_AUTH_SCHEME_BASIC; + } else { + giterr_set(GITERR_NET, "invalid authentication scheme"); + return -1; + } + + return _apply_userpass_credential(request, WINHTTP_AUTH_TARGET_SERVER, + native_scheme, cred); +} + +static int apply_default_credentials(HINTERNET request, int mechanisms) { /* Either the caller explicitly requested that default credentials be passed, * or our fallback credential callback was invoked and checked that the target @@ -177,6 +165,12 @@ static int apply_default_credentials(HINTERNET request) * to Internet Explorer security zones, but in fact does not. */ DWORD data = WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW; + if ((mechanisms & GIT_WINHTTP_AUTH_NTLM) == 0 && + (mechanisms & GIT_WINHTTP_AUTH_NEGOTIATE) == 0) { + giterr_set(GITERR_NET, "invalid authentication scheme"); + return -1; + } + if (!WinHttpSetOption(request, WINHTTP_OPTION_AUTOLOGON_POLICY, &data, sizeof(DWORD))) return -1; @@ -453,7 +447,7 @@ static int winhttp_stream_connect(winhttp_stream *s) if (t->proxy_cred) { if (t->proxy_cred->credtype == GIT_CREDTYPE_USERPASS_PLAINTEXT) { - if ((error = apply_basic_credential_proxy(s->request, t->proxy_cred)) < 0) + if ((error = apply_userpass_credential_proxy(s->request, t->proxy_cred)) < 0) goto on_error; } } @@ -550,13 +544,11 @@ static int winhttp_stream_connect(winhttp_stream *s) /* If we have a credential on the subtransport, apply it to the request */ if (t->cred && t->cred->credtype == GIT_CREDTYPE_USERPASS_PLAINTEXT && - t->auth_mechanism == GIT_WINHTTP_AUTH_BASIC && - apply_basic_credential(s->request, t->cred) < 0) + apply_userpass_credential(s->request, t->auth_mechanisms, t->cred) < 0) goto on_error; else if (t->cred && t->cred->credtype == GIT_CREDTYPE_DEFAULT && - t->auth_mechanism == GIT_WINHTTP_AUTH_NEGOTIATE && - apply_default_credentials(s->request) < 0) + apply_default_credentials(s->request, t->auth_mechanisms) < 0) goto on_error; /* If no other credentials have been applied and the URL has username and @@ -565,7 +557,7 @@ static int winhttp_stream_connect(winhttp_stream *s) if (!t->url_cred && git_cred_userpass_plaintext_new(&t->url_cred, t->connection_data.user, t->connection_data.pass) < 0) goto on_error; - if (apply_basic_credential(s->request, t->url_cred) < 0) + if (apply_userpass_credential(s->request, GIT_WINHTTP_AUTH_BASIC, t->url_cred) < 0) goto on_error; } @@ -585,12 +577,12 @@ on_error: static int parse_unauthorized_response( HINTERNET request, int *allowed_types, - int *auth_mechanism) + int *allowed_mechanisms) { DWORD supported, first, target; *allowed_types = 0; - *auth_mechanism = 0; + *allowed_mechanisms = 0; /* WinHttpQueryHeaders() must be called before WinHttpQueryAuthSchemes(). * We can assume this was already done, since we know we are unauthorized. @@ -600,15 +592,20 @@ static int parse_unauthorized_response( return -1; } - if (WINHTTP_AUTH_SCHEME_BASIC & supported) { + if (WINHTTP_AUTH_SCHEME_NTLM & supported) { *allowed_types |= GIT_CREDTYPE_USERPASS_PLAINTEXT; - *auth_mechanism = GIT_WINHTTP_AUTH_BASIC; + *allowed_types |= GIT_CREDTYPE_DEFAULT; + *allowed_mechanisms = GIT_WINHTTP_AUTH_NEGOTIATE; } - if ((WINHTTP_AUTH_SCHEME_NTLM & supported) || - (WINHTTP_AUTH_SCHEME_NEGOTIATE & supported)) { + if (WINHTTP_AUTH_SCHEME_NEGOTIATE & supported) { *allowed_types |= GIT_CREDTYPE_DEFAULT; - *auth_mechanism = GIT_WINHTTP_AUTH_NEGOTIATE; + *allowed_mechanisms = GIT_WINHTTP_AUTH_NEGOTIATE; + } + + if (WINHTTP_AUTH_SCHEME_BASIC & supported) { + *allowed_types |= GIT_CREDTYPE_USERPASS_PLAINTEXT; + *allowed_mechanisms |= GIT_WINHTTP_AUTH_BASIC; } return 0; @@ -1029,7 +1026,7 @@ replay: if (status_code == HTTP_STATUS_PROXY_AUTH_REQ) { int allowed_types; - if (parse_unauthorized_response(s->request, &allowed_types, &t->auth_mechanism) < 0) + if (parse_unauthorized_response(s->request, &allowed_types, &t->auth_mechanisms) < 0) return -1; /* TODO: extract the username from the url, no payload? */ @@ -1049,7 +1046,7 @@ replay: if (HTTP_STATUS_DENIED == status_code && get_verb == s->verb) { int allowed_types; - if (parse_unauthorized_response(s->request, &allowed_types, &t->auth_mechanism) < 0) + if (parse_unauthorized_response(s->request, &allowed_types, &t->auth_mechanisms) < 0) return -1; if (allowed_types) { From ca05857e71f8d11582b1ad82f63c6a61e96fe20e Mon Sep 17 00:00:00 2001 From: David Turner Date: Wed, 23 Nov 2016 18:26:19 -0500 Subject: [PATCH 037/366] Fix formatting Signed-off-by: David Turner --- src/submodule.c | 126 ++++++++++++++++++++++++------------------------ 1 file changed, 63 insertions(+), 63 deletions(-) diff --git a/src/submodule.c b/src/submodule.c index 6d6b314d6..46462f165 100644 --- a/src/submodule.c +++ b/src/submodule.c @@ -324,89 +324,89 @@ done: static int submodules_from_index(git_strmap *map, git_index *idx, git_config *cfg) { - int error; - git_iterator *i; - const git_index_entry *entry; - git_buf name = GIT_BUF_INIT; + int error; + git_iterator *i; + const git_index_entry *entry; + git_buf name = GIT_BUF_INIT; - if ((error = git_iterator_for_index(&i, git_index_owner(idx), idx, NULL)) < 0) - return error; + if ((error = git_iterator_for_index(&i, git_index_owner(idx), idx, NULL)) < 0) + return error; - while (!(error = git_iterator_advance(&entry, i))) { - khiter_t pos = git_strmap_lookup_index(map, entry->path); - git_submodule *sm; + while (!(error = git_iterator_advance(&entry, i))) { + khiter_t pos = git_strmap_lookup_index(map, entry->path); + git_submodule *sm; - git_buf_clear(&name); - if (!name_from_path(&name, cfg, entry->path)) { - git_strmap_lookup_index(map, name.ptr); - } + git_buf_clear(&name); + if (!name_from_path(&name, cfg, entry->path)) { + git_strmap_lookup_index(map, name.ptr); + } - if (git_strmap_valid_index(map, pos)) { - sm = git_strmap_value_at(map, pos); + if (git_strmap_valid_index(map, pos)) { + sm = git_strmap_value_at(map, pos); - if (S_ISGITLINK(entry->mode)) - submodule_update_from_index_entry(sm, entry); - else - sm->flags |= GIT_SUBMODULE_STATUS__INDEX_NOT_SUBMODULE; - } else if (S_ISGITLINK(entry->mode)) { - if (!submodule_get_or_create(&sm, git_index_owner(idx), map, name.ptr ? name.ptr : entry->path)) { - submodule_update_from_index_entry(sm, entry); - git_submodule_free(sm); - } - } - } + if (S_ISGITLINK(entry->mode)) + submodule_update_from_index_entry(sm, entry); + else + sm->flags |= GIT_SUBMODULE_STATUS__INDEX_NOT_SUBMODULE; + } else if (S_ISGITLINK(entry->mode)) { + if (!submodule_get_or_create(&sm, git_index_owner(idx), map, name.ptr ? name.ptr : entry->path)) { + submodule_update_from_index_entry(sm, entry); + git_submodule_free(sm); + } + } + } - if (error == GIT_ITEROVER) - error = 0; + if (error == GIT_ITEROVER) + error = 0; - git_buf_free(&name); - git_iterator_free(i); + git_buf_free(&name); + git_iterator_free(i); - return error; + return error; } static int submodules_from_head(git_strmap *map, git_tree *head, git_config *cfg) { - int error; - git_iterator *i; - const git_index_entry *entry; - git_buf name = GIT_BUF_INIT; + int error; + git_iterator *i; + const git_index_entry *entry; + git_buf name = GIT_BUF_INIT; - if ((error = git_iterator_for_tree(&i, head, NULL)) < 0) - return error; + if ((error = git_iterator_for_tree(&i, head, NULL)) < 0) + return error; - while (!(error = git_iterator_advance(&entry, i))) { - khiter_t pos = git_strmap_lookup_index(map, entry->path); - git_submodule *sm; + while (!(error = git_iterator_advance(&entry, i))) { + khiter_t pos = git_strmap_lookup_index(map, entry->path); + git_submodule *sm; - git_buf_clear(&name); - if (!name_from_path(&name, cfg, entry->path)) { - git_strmap_lookup_index(map, name.ptr); - } + git_buf_clear(&name); + if (!name_from_path(&name, cfg, entry->path)) { + git_strmap_lookup_index(map, name.ptr); + } - if (git_strmap_valid_index(map, pos)) { - sm = git_strmap_value_at(map, pos); + if (git_strmap_valid_index(map, pos)) { + sm = git_strmap_value_at(map, pos); - if (S_ISGITLINK(entry->mode)) - submodule_update_from_head_data(sm, entry->mode, &entry->id); - else - sm->flags |= GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE; - } else if (S_ISGITLINK(entry->mode)) { - if (!submodule_get_or_create(&sm, git_tree_owner(head), map, name.ptr ? name.ptr : entry->path)) { - submodule_update_from_head_data( - sm, entry->mode, &entry->id); - git_submodule_free(sm); - } - } - } + if (S_ISGITLINK(entry->mode)) + submodule_update_from_head_data(sm, entry->mode, &entry->id); + else + sm->flags |= GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE; + } else if (S_ISGITLINK(entry->mode)) { + if (!submodule_get_or_create(&sm, git_tree_owner(head), map, name.ptr ? name.ptr : entry->path)) { + submodule_update_from_head_data( + sm, entry->mode, &entry->id); + git_submodule_free(sm); + } + } + } - if (error == GIT_ITEROVER) - error = 0; + if (error == GIT_ITEROVER) + error = 0; - git_buf_free(&name); - git_iterator_free(i); + git_buf_free(&name); + git_iterator_free(i); - return error; + return error; } /* If have_sm is true, sm is populated, otherwise map an repo are. */ From 4d99c4cfc604bb141fd4e1423e934ebd3fb7e2a7 Mon Sep 17 00:00:00 2001 From: Brock Peabody Date: Wed, 23 Nov 2016 18:32:48 -0500 Subject: [PATCH 038/366] Allow for caching of submodules. Added `git_repository_submodule_cache_all` to initialze a cache of submodules on the repository so that operations looking up N submodules are O(N) and not O(N^2). Added a `git_repository_submodule_cache_clear` function to remove the cache. Also optimized the function that loads all submodules as it was itself O(N^2) w.r.t the number of submodules, having to loop through the `.gitmodules` file once per submodule. I changed it to process the `.gitmodules` file once, into a map. Signed-off-by: David Turner --- include/git2/sys/repository.h | 29 +++++++++ src/repository.c | 33 ++++++++++ src/repository.h | 1 + src/submodule.c | 119 +++++++++++++++++++++++----------- src/submodule.h | 3 + tests/submodule/lookup.c | 25 +++++++ 6 files changed, 171 insertions(+), 39 deletions(-) diff --git a/include/git2/sys/repository.h b/include/git2/sys/repository.h index 800396c86..0c9142143 100644 --- a/include/git2/sys/repository.h +++ b/include/git2/sys/repository.h @@ -135,6 +135,35 @@ GIT_EXTERN(void) git_repository_set_index(git_repository *repo, git_index *index */ GIT_EXTERN(int) git_repository_set_bare(git_repository *repo); +/** + * Load and cache all submodules. + * + * Because the `.gitmodules` file is unstructured, loading submodules is an + * O(N) operation. Any operation (such as `git_rebase_init`) that requires + * accessing all submodules is O(N^2) in the number of submodules, if it + * has to look each one up individually. This function loads all submodules + * and caches them so that subsequent calls to `git_submodule_lookup` are O(1). + * + * @param repo the repository whose submodules will be cached. + */ +GIT_EXTERN(int) git_repository_submodule_cache_all( + git_repository *repo); + +/** + * Clear the submodule cache. + * + * Clear the submodule cache populated by `git_repository_submodule_cache_all`. + * If there is no cache, do nothing. + * + * The cache incorporates data from the repository's configuration, as well + * as the state of the working tree, the index, and HEAD. So any time any + * of these has changed, the cache might become invalid. + * + * @param repo the repository whose submodule cache will be cleared + */ +GIT_EXTERN(int) git_repository_submodule_cache_clear( + git_repository *repo); + /** @} */ GIT_END_DECL #endif diff --git a/src/repository.c b/src/repository.c index 60299193f..2185632bf 100644 --- a/src/repository.c +++ b/src/repository.c @@ -27,6 +27,10 @@ #include "merge.h" #include "diff_driver.h" #include "annotated_commit.h" +#include "submodule.h" + +GIT__USE_STRMAP +#include "strmap.h" #ifdef GIT_WIN32 # include "win32/w32_util.h" @@ -109,6 +113,7 @@ void git_repository__cleanup(git_repository *repo) { assert(repo); + git_repository_submodule_cache_clear(repo); git_cache_clear(&repo->objects); git_attr_cache_flush(repo); @@ -2541,3 +2546,31 @@ int git_repository_set_ident(git_repository *repo, const char *name, const char return 0; } + +int git_repository_submodule_cache_all(git_repository *repo) +{ + int error; + + assert(repo); + + if ((error = git_strmap_alloc(&repo->submodule_cache))) + return error; + + error = git_submodule__map(repo, repo->submodule_cache); + return error; +} + +int git_repository_submodule_cache_clear(git_repository *repo) +{ + git_submodule *sm; + assert(repo); + if (repo->submodule_cache == NULL) { + return 0; + } + git_strmap_foreach_value(repo->submodule_cache, sm, { + git_submodule_free(sm); + }); + git_strmap_free(repo->submodule_cache); + repo->submodule_cache = 0; + return 0; +} diff --git a/src/repository.h b/src/repository.h index b259bea3b..9d276f376 100644 --- a/src/repository.h +++ b/src/repository.h @@ -143,6 +143,7 @@ struct git_repository { git_atomic attr_session_key; git_cvar_value cvar_cache[GIT_CVAR_CACHE_MAX]; + git_strmap *submodule_cache; }; GIT_INLINE(git_attr_cache *) git_repository_attr_cache(git_repository *repo) diff --git a/src/submodule.c b/src/submodule.c index 46462f165..6996006dc 100644 --- a/src/submodule.c +++ b/src/submodule.c @@ -149,40 +149,53 @@ static int find_by_path(const git_config_entry *entry, void *payload) } /** - * Find out the name of a submodule from its path + * Release the name map returned by 'load_submodule_names'. */ -static int name_from_path(git_buf *out, git_config *cfg, const char *path) +static void free_submodule_names(git_strmap *names) +{ + git_buf *name = 0; + if (names == NULL) + return; + git_strmap_foreach_value(names, name, { + git__free(name); + }); + git_strmap_free(names); + return; +} + +/** + * Map submodule paths to names. + * TODO: for some use-cases, this might need case-folding on a + * case-insensitive filesystem + */ +static int load_submodule_names(git_strmap *out, git_config *cfg) { const char *key = "submodule\\..*\\.path"; git_config_iterator *iter; git_config_entry *entry; - int error; + git_buf buf = GIT_BUF_INIT; + int rval; + int error = 0; if ((error = git_config_iterator_glob_new(&iter, cfg, key)) < 0) return error; - while ((error = git_config_next(&entry, iter)) == 0) { + while (git_config_next(&entry, iter) == 0) { const char *fdot, *ldot; - /* TODO: this should maybe be strcasecmp on a case-insensitive fs */ - if (strcmp(path, entry->value) != 0) - continue; - fdot = strchr(entry->name, '.'); ldot = strrchr(entry->name, '.'); - git_buf_clear(out); - git_buf_put(out, fdot + 1, ldot - fdot - 1); - goto cleanup; + git_buf_put(&buf, fdot + 1, ldot - fdot - 1); + git_strmap_insert(out, entry->value, git_buf_detach(&buf), rval); + if (rval < 0) { + giterr_set(GITERR_NOMEMORY, "Error inserting submodule into hash table"); + free_submodule_names(out); + return -1; + } } - if (error == GIT_ITEROVER) { - giterr_set(GITERR_SUBMODULE, "could not find a submodule name for '%s'", path); - error = GIT_ENOTFOUND; - } - -cleanup: git_config_iterator_free(iter); - return error; + return 0; } int git_submodule_lookup( @@ -196,6 +209,17 @@ int git_submodule_lookup( assert(repo && name); + if (repo->submodule_cache != NULL) { + khiter_t pos = git_strmap_lookup_index(repo->submodule_cache, name); + if (git_strmap_valid_index(repo->submodule_cache, pos)) { + if (out) { + *out = git_strmap_value_at(repo->submodule_cache, pos); + GIT_REFCOUNT_INC(*out); + } + return 0; + } + } + if ((error = submodule_alloc(&sm, repo, name)) < 0) return error; @@ -327,20 +351,18 @@ static int submodules_from_index(git_strmap *map, git_index *idx, git_config *cf int error; git_iterator *i; const git_index_entry *entry; - git_buf name = GIT_BUF_INIT; + git_strmap *names = 0; + git_strmap_alloc(&names); + if ((error = load_submodule_names(names, cfg))) + goto done; if ((error = git_iterator_for_index(&i, git_index_owner(idx), idx, NULL)) < 0) - return error; + goto done; while (!(error = git_iterator_advance(&entry, i))) { khiter_t pos = git_strmap_lookup_index(map, entry->path); git_submodule *sm; - git_buf_clear(&name); - if (!name_from_path(&name, cfg, entry->path)) { - git_strmap_lookup_index(map, name.ptr); - } - if (git_strmap_valid_index(map, pos)) { sm = git_strmap_value_at(map, pos); @@ -349,7 +371,17 @@ static int submodules_from_index(git_strmap *map, git_index *idx, git_config *cf else sm->flags |= GIT_SUBMODULE_STATUS__INDEX_NOT_SUBMODULE; } else if (S_ISGITLINK(entry->mode)) { - if (!submodule_get_or_create(&sm, git_index_owner(idx), map, name.ptr ? name.ptr : entry->path)) { + khiter_t name_pos; + const char *name; + + name_pos = git_strmap_lookup_index(names, entry->path); + if (git_strmap_valid_index(names, name_pos)) { + name = git_strmap_value_at(names, name_pos); + } else { + name = entry->path; + } + + if (!submodule_get_or_create(&sm, git_index_owner(idx), map, name)) { submodule_update_from_index_entry(sm, entry); git_submodule_free(sm); } @@ -359,8 +391,9 @@ static int submodules_from_index(git_strmap *map, git_index *idx, git_config *cf if (error == GIT_ITEROVER) error = 0; - git_buf_free(&name); +done: git_iterator_free(i); + free_submodule_names(names); return error; } @@ -370,20 +403,18 @@ static int submodules_from_head(git_strmap *map, git_tree *head, git_config *cfg int error; git_iterator *i; const git_index_entry *entry; - git_buf name = GIT_BUF_INIT; + git_strmap *names = 0; + git_strmap_alloc(&names); + if ((error = load_submodule_names(names, cfg))) + goto done; if ((error = git_iterator_for_tree(&i, head, NULL)) < 0) - return error; + goto done; while (!(error = git_iterator_advance(&entry, i))) { khiter_t pos = git_strmap_lookup_index(map, entry->path); git_submodule *sm; - git_buf_clear(&name); - if (!name_from_path(&name, cfg, entry->path)) { - git_strmap_lookup_index(map, name.ptr); - } - if (git_strmap_valid_index(map, pos)) { sm = git_strmap_value_at(map, pos); @@ -392,7 +423,17 @@ static int submodules_from_head(git_strmap *map, git_tree *head, git_config *cfg else sm->flags |= GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE; } else if (S_ISGITLINK(entry->mode)) { - if (!submodule_get_or_create(&sm, git_tree_owner(head), map, name.ptr ? name.ptr : entry->path)) { + khiter_t name_pos; + const char *name; + + name_pos = git_strmap_lookup_index(names, entry->path); + if (git_strmap_valid_index(names, name_pos)) { + name = git_strmap_value_at(names, name_pos); + } else { + name = entry->path; + } + + if (!submodule_get_or_create(&sm, git_tree_owner(head), map, name)) { submodule_update_from_head_data( sm, entry->mode, &entry->id); git_submodule_free(sm); @@ -403,8 +444,9 @@ static int submodules_from_head(git_strmap *map, git_tree *head, git_config *cfg if (error == GIT_ITEROVER) error = 0; - git_buf_free(&name); +done: git_iterator_free(i); + free_submodule_names(names); return error; } @@ -416,7 +458,7 @@ typedef struct { git_repository *repo; } lfc_data; -static int all_submodules(git_repository *repo, git_strmap *map) +int git_submodule__map(git_repository *repo, git_strmap *map) { int error = 0; git_index *idx = NULL; @@ -509,7 +551,7 @@ int git_submodule_foreach( if ((error = git_strmap_alloc(&submodules)) < 0) return error; - if ((error = all_submodules(repo, submodules)) < 0) + if ((error = git_submodule__map(repo, submodules)) < 0) goto done; if (!(error = git_vector_init( @@ -1566,7 +1608,6 @@ int git_submodule_location(unsigned int *location, git_submodule *sm) location, NULL, NULL, NULL, sm, GIT_SUBMODULE_IGNORE_ALL); } - /* * INTERNAL FUNCTIONS */ diff --git a/src/submodule.h b/src/submodule.h index 2ef2031b3..456a93979 100644 --- a/src/submodule.h +++ b/src/submodule.h @@ -143,4 +143,7 @@ extern int git_submodule_parse_ignore( extern int git_submodule_parse_update( git_submodule_update_t *out, const char *value); +extern int git_submodule__map( + git_repository *repo, + git_strmap *map); #endif diff --git a/tests/submodule/lookup.c b/tests/submodule/lookup.c index 148f9273e..e36fc44e0 100644 --- a/tests/submodule/lookup.c +++ b/tests/submodule/lookup.c @@ -388,3 +388,28 @@ void test_submodule_lookup__renamed(void) cl_git_pass(git_submodule_foreach(g_repo, sm_lookup_cb, &data)); cl_assert_equal_i(8, data.count); } + +void test_submodule_lookup_cached(void) { + git_submodule *sm; + git_submodule *sm2; + /* See that the simple tests still pass. */ + + git_repository_submodule_cache_all(g_repo); + test_submodule_lookup__simple_lookup(); + git_repository_submodule_cache_clear(g_repo); + test_submodule_lookup__simple_lookup(); + + /* Check that subsequent calls return different objects when cached. */ + git_repository_submodule_cache_all(g_repo); + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); + cl_git_pass(git_submodule_lookup(&sm2, g_repo, "sm_unchanged")); + cl_assert_equal_p(sm, sm2); + git_submodule_free(sm2); + + /* and that we get new objects again after clearing the cache. */ + git_repository_submodule_cache_clear(g_repo); + cl_git_pass(git_submodule_lookup(&sm2, g_repo, "sm_unchanged")); + cl_assert(sm != sm2); + git_submodule_free(sm); + git_submodule_free(sm2); +} From 673dff88a2c78766609a7023167acb5a882fb84d Mon Sep 17 00:00:00 2001 From: Brock Peabody Date: Wed, 23 Nov 2016 18:32:55 -0500 Subject: [PATCH 039/366] Skip submodule head/index update when caching. `git_submodule_status` is very slow, bottlenecked on `git_repository_head_tree`, which it uses through `submodule_update_head`. If the user has requested submodule caching, assume that they want this status cached too and skip it. Signed-off-by: David Turner --- src/submodule.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/submodule.c b/src/submodule.c index 6996006dc..3099db6cf 100644 --- a/src/submodule.c +++ b/src/submodule.c @@ -1544,13 +1544,22 @@ int git_submodule__status( return 0; } - /* refresh the index OID */ - if (submodule_update_index(sm) < 0) - return -1; + /* If the user has requested caching submodule state, performing these + * expensive operations (especially `submodule_update_head`, which is + * bottlenecked on `git_repository_head_tree`) eliminates much of the + * advantage. We will, therefore, interpret the request for caching to + * apply here to and skip them. + */ - /* refresh the HEAD OID */ - if (submodule_update_head(sm) < 0) - return -1; + if (sm->repo->submodule_cache == NULL) { + /* refresh the index OID */ + if (submodule_update_index(sm) < 0) + return -1; + + /* refresh the HEAD OID */ + if (submodule_update_head(sm) < 0) + return -1; + } /* for ignore == dirty, don't scan the working directory */ if (ign == GIT_SUBMODULE_IGNORE_DIRTY) { From d030bba9fa64c4363368f9e3e0ed3f115dc06dc2 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Sat, 21 Jan 2017 17:15:33 +0000 Subject: [PATCH 040/366] indexer: only delete temp file if it was unused Only try to `unlink` our temp file when we know that we didn't copy it into its permanent location. --- src/indexer.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/indexer.c b/src/indexer.c index 3d1c81c86..aa5646023 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -33,7 +33,7 @@ struct entry { struct git_indexer { unsigned int parsed_header :1, - opened_pack :1, + pack_committed :1, have_stream :1, have_delta :1; struct git_pack_header hdr; @@ -1060,6 +1060,7 @@ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats) /* And don't forget to rename the packfile to its new place. */ p_rename(idx->pack->pack_name, git_buf_cstr(&filename)); + idx->pack_committed = 1; git_buf_free(&filename); git_hash_ctx_cleanup(&ctx); @@ -1092,12 +1093,13 @@ void git_indexer_free(git_indexer *idx) /* Try to delete the temporary file in case it was not committed. */ git_mwindow_free_all(&idx->pack->mwf); + /* We need to close the descriptor here so Windows doesn't choke on unlink */ - if (idx->pack->mwf.fd != -1) { + if (idx->pack->mwf.fd != -1) p_close(idx->pack->mwf.fd); - idx->pack->mwf.fd = -1; - } - p_unlink(idx->pack->pack_name); + + if (!idx->pack_committed) + p_unlink(idx->pack->pack_name); if (!git_mutex_lock(&git__mwindow_mutex)) { git_packfile_free(idx->pack); From bf339ab0ef64754dcc8e7506dd0d23629815a65a Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Sat, 21 Jan 2017 14:51:31 -0500 Subject: [PATCH 041/366] indexer: introduce `git_packfile_close` Encapsulation! --- src/indexer.c | 13 +++---------- src/pack.c | 17 +++++++++++++---- src/pack.h | 1 + 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/indexer.c b/src/indexer.c index 05a02f646..805c36ea4 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -1091,17 +1091,10 @@ void git_indexer_free(git_indexer *idx) git_vector_free_deep(&idx->deltas); - /* Try to delete the temporary file in case it was not committed. */ - git_mwindow_free_all(&idx->pack->mwf); - - /* We need to close the descriptor here so Windows doesn't choke on unlink */ - if (idx->pack->mwf.fd != -1) - p_close(idx->pack->mwf.fd); - - if (!idx->pack_committed) - p_unlink(idx->pack->pack_name); - if (!git_mutex_lock(&git__mwindow_mutex)) { + if (!idx->pack_committed) + git_packfile_close(idx->pack, true); + git_packfile_free(idx->pack); git_mutex_unlock(&git__mwindow_mutex); } diff --git a/src/pack.c b/src/pack.c index 345ff5259..243719d9c 100644 --- a/src/pack.c +++ b/src/pack.c @@ -991,6 +991,18 @@ git_off_t get_delta_base( * ***********************************************************/ +void git_packfile_close(struct git_pack_file *p, bool unlink_packfile) +{ + if (p->mwf.fd >= 0) { + git_mwindow_free_all_locked(&p->mwf); + p_close(p->mwf.fd); + p->mwf.fd = -1; + } + + if (unlink_packfile) + p_unlink(p->pack_name); +} + void git_packfile_free(struct git_pack_file *p) { if (!p) @@ -998,10 +1010,7 @@ void git_packfile_free(struct git_pack_file *p) cache_free(&p->bases); - if (p->mwf.fd >= 0) { - git_mwindow_free_all_locked(&p->mwf); - p_close(p->mwf.fd); - } + git_packfile_close(p, false); pack_index_free(p); diff --git a/src/pack.h b/src/pack.h index 5302db5b7..e2bf165f4 100644 --- a/src/pack.h +++ b/src/pack.h @@ -149,6 +149,7 @@ git_off_t get_delta_base(struct git_pack_file *p, git_mwindow **w_curs, git_off_t *curpos, git_otype type, git_off_t delta_obj_offset); +void git_packfile_close(struct git_pack_file *p, bool unlink_packfile); void git_packfile_free(struct git_pack_file *p); int git_packfile_alloc(struct git_pack_file **pack_out, const char *path); From 87b7a7051b8aa50bddc806a46240e7b15e3e23cc Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Sat, 21 Jan 2017 15:44:57 -0500 Subject: [PATCH 042/366] indexer: avoid warning about `idx->pack` It must be non-NULL to have a valid `git_indexer`. --- src/indexer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/indexer.c b/src/indexer.c index 805c36ea4..951d7179c 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -1081,7 +1081,7 @@ void git_indexer_free(git_indexer *idx) git_vector_free_deep(&idx->objects); - if (idx->pack && idx->pack->idx_cache) { + if (idx->pack->idx_cache) { struct git_pack_entry *pentry; kh_foreach_value( idx->pack->idx_cache, pentry, { git__free(pentry); }); From 3b4eb107c21eb855dd651bc2e5904c0b29ece9b7 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Sat, 21 Jan 2017 22:40:37 +0000 Subject: [PATCH 043/366] CHANGELOG: move `git_submodule_update_option` changes The changes to `git_submodule_update_option` are now landing in v.Next. --- CHANGELOG.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 34c5d8424..0ae75e156 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,10 @@ v0.25 + 1 ### Breaking API changes +* `clone_checkout_strategy` has been removed from + `git_submodule_update_option`. The checkout strategy used to clone will + be the same strategy specified in `checkout_opts`. + v0.25 ------- @@ -135,10 +139,6 @@ v0.25 * `git_blob_create_fromchunks()` has been removed in favour of `git_blob_create_fromstream()`. -* `clone_checkout_strategy` has been removed from - `git_submodule_update_option`. The checkout strategy used to clone will - be the same strategy specified in `checkout_opts`. - ### Breaking API changes * `git_packbuilder_object_count` and `git_packbuilder_written` now From 1910a04adbdd58e5517b38488433f655066c3586 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 30 Dec 2016 12:42:42 -0500 Subject: [PATCH 044/366] winhttp: set proper cert failure error messages Set up a WinHTTP status callback; inspect the WinHTTP status for WINHTTP_CALLBACK_STATUS_SECURE_FAILURE, and convert the status code to a useful message for callers. --- src/transports/winhttp.c | 54 ++++++++++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 7 deletions(-) diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c index 79b3ac6b4..0d304d6b3 100644 --- a/src/transports/winhttp.c +++ b/src/transports/winhttp.c @@ -242,8 +242,12 @@ static int certificate_check(winhttp_stream *s, int valid) git_cert_x509 cert; /* If there is no override, we should fail if WinHTTP doesn't think it's fine */ - if (t->owner->certificate_check_cb == NULL && !valid) + if (t->owner->certificate_check_cb == NULL && !valid) { + if (!giterr_last()) + giterr_set(GITERR_NET, "unknown certificate check failure"); + return GIT_ECERTIFICATE; + } if (t->owner->certificate_check_cb == NULL || !t->connection_data.use_ssl) return 0; @@ -691,6 +695,38 @@ static int user_agent(git_buf *ua) return git_buf_putc(ua, ')'); } +static void CALLBACK winhttp_status( + HINTERNET connection, + DWORD_PTR ctx, + DWORD code, + LPVOID info, + DWORD info_len) +{ + DWORD status; + + if (code != WINHTTP_CALLBACK_STATUS_SECURE_FAILURE) + return; + + status = *((DWORD *)info); + + if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID)) + giterr_set(GITERR_NET, "SSL certificate issued for different common name"); + else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID)) + giterr_set(GITERR_NET, "SSL certificate has expired"); + else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA)) + giterr_set(GITERR_NET, "SSL certificate signed by unknown CA"); + else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT)) + giterr_set(GITERR_NET, "SSL certificate is invalid"); + else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED)) + giterr_set(GITERR_NET, "certificate revocation check failed"); + else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED)) + giterr_set(GITERR_NET, "SSL certificate was revoked"); + else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR)) + giterr_set(GITERR_NET, "security libraries could not be loaded"); + else + giterr_set(GITERR_NET, "unknown security error %d", status); +} + static int winhttp_connect( winhttp_subtransport *t) { @@ -760,6 +796,11 @@ static int winhttp_connect( goto on_error; } + if (WinHttpSetStatusCallback(t->connection, winhttp_status, WINHTTP_CALLBACK_FLAG_SECURE_FAILURE, 0) == WINHTTP_INVALID_STATUS_CALLBACK) { + giterr_set(GITERR_OS, "failed to set status callback"); + goto on_error; + } + error = 0; on_error: @@ -798,16 +839,15 @@ static int send_request(winhttp_stream *s, size_t len, int ignore_length) int request_failed = 0, cert_valid = 1, error = 0; DWORD ignore_flags; - if ((error = do_send_request(s, len, ignore_length)) < 0) - request_failed = 1; - - if (request_failed) { + giterr_clear(); + if ((error = do_send_request(s, len, ignore_length)) < 0) { if (GetLastError() != ERROR_WINHTTP_SECURE_FAILURE) { giterr_set(GITERR_OS, "failed to send request"); return -1; - } else { - cert_valid = 0; } + + request_failed = 1; + cert_valid = 0; } giterr_clear(); From 28d0ba0ba5f41f71997a15e81bbda4ed2d1b896a Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Sat, 21 Jan 2017 23:45:23 +0000 Subject: [PATCH 045/366] symbolic ref target validation: fixups Fixups requested in #3912. --- include/git2/common.h | 18 ++++++++---------- src/refs.c | 38 +++++++++----------------------------- src/refs.h | 2 +- src/settings.c | 2 +- 4 files changed, 19 insertions(+), 41 deletions(-) diff --git a/include/git2/common.h b/include/git2/common.h index 02d263048..3304f46d2 100644 --- a/include/git2/common.h +++ b/include/git2/common.h @@ -157,7 +157,7 @@ typedef enum { GIT_OPT_SET_SSL_CERT_LOCATIONS, GIT_OPT_SET_USER_AGENT, GIT_OPT_ENABLE_STRICT_OBJECT_CREATION, - GIT_OPT_ENABLE_SYMBOLIC_REF_TARGET_VALIDATION, + GIT_OPT_ENABLE_STRICT_SYMBOLIC_REF_CREATION, GIT_OPT_SET_SSL_CIPHERS, GIT_OPT_GET_USER_AGENT, } git_libgit2_opt_t; @@ -272,16 +272,14 @@ typedef enum { * > will be validated when creating a new commit. This defaults * > to disabled. * - * * opts(GIT_OPT_ENABLE_SYMBOLIC_REF_TARGET_VALIDATION, int enabled) + * * opts(GIT_OPT_ENABLE_STRICT_SYMBOLIC_REF_CREATION, int enabled) * - * > Validate the target of a symbolic ref when creating it. - * > For example, 'foobar' is not a valid ref, - * > therefore 'foobar' is not a valid target - * > for a symbolic ref by default, - * > where as 'refs/heads/foobar' is. - * > Disabling this bypasses validation so that an arbitrary - * > strings such as 'foobar' can be used for a symbolic ref target. - * > This defaults to enabled. + * > Validate the target of a symbolic ref when creating it. For + * > example, `foobar` is not a valid ref, therefore `foobar` is + * > not a valid target for a symbolic ref by default, whereas + * > `refs/heads/foobar` is. Disabling this bypasses validation + * > so that an arbitrary strings such as `foobar` can be used + * > for a symbolic ref target. This defaults to enabled. * * * opts(GIT_OPT_SET_SSL_CIPHERS, const char *ciphers) * diff --git a/src/refs.c b/src/refs.c index c77653da8..da6add0b4 100644 --- a/src/refs.c +++ b/src/refs.c @@ -177,7 +177,7 @@ int git_reference_name_to_id( return 0; } -static int reference__normalize_for_repo( +static int reference_normalize_for_repo( git_refname_t out, git_repository *repo, const char *name, @@ -190,29 +190,12 @@ static int reference__normalize_for_repo( precompose) flags |= GIT_REF_FORMAT__PRECOMPOSE_UNICODE; - if (!validate) { - flags |= GIT_REF_VALIDATION_DISABLE; - } + if (!validate) + flags |= GIT_REF_FORMAT__VALIDATION_DISABLE; return git_reference_normalize_name(out, GIT_REFNAME_MAX, name, flags); } -static int reference_normalize_for_repo( - git_refname_t out, - git_repository *repo, - const char *name) -{ - return reference__normalize_for_repo(out, repo, name, true); -} - -static int reference_normalize_for_repo_without_validation( - git_refname_t out, - git_repository *repo, - const char *name) -{ - return reference__normalize_for_repo(out, repo, name, false); -} - int git_reference_lookup_resolved( git_reference **ref_out, git_repository *repo, @@ -236,7 +219,7 @@ int git_reference_lookup_resolved( scan_type = GIT_REF_SYMBOLIC; - if ((error = reference_normalize_for_repo(scan_name, repo, name)) < 0) + if ((error = reference_normalize_for_repo(scan_name, repo, name, true)) < 0) return error; if ((error = git_repository_refdb__weakptr(&refdb, repo)) < 0) @@ -406,7 +389,7 @@ static int reference__create( if (ref_out) *ref_out = NULL; - error = reference_normalize_for_repo(normalized, repo, name); + error = reference_normalize_for_repo(normalized, repo, name, true); if (error < 0) return error; @@ -427,11 +410,8 @@ static int reference__create( } else { git_refname_t normalized_target; - if (git_reference__enable_symbolic_ref_target_validation) { - error = reference_normalize_for_repo(normalized_target, repo, symbolic); - } else { - error = reference_normalize_for_repo_without_validation(normalized_target, repo, symbolic); - } + error = reference_normalize_for_repo(normalized_target, repo, + symbolic, git_reference__enable_symbolic_ref_target_validation); if (error < 0) return error; @@ -612,7 +592,7 @@ static int reference__rename(git_reference **out, git_reference *ref, const char assert(ref && new_name && signature); if ((error = reference_normalize_for_repo( - normalized, git_reference_owner(ref), new_name)) < 0) + normalized, git_reference_owner(ref), new_name, true)) < 0) return error; @@ -905,7 +885,7 @@ int git_reference__normalize_name( int segment_len, segments_count = 0, error = GIT_EINVALIDSPEC; unsigned int process_flags; bool normalize = (buf != NULL); - bool validate = (flags & GIT_REF_VALIDATION_DISABLE) == 0; + bool validate = (flags & GIT_REF_FORMAT__VALIDATION_DISABLE) == 0; #ifdef GIT_USE_ICONV git_path_iconv_t ic = GIT_PATH_ICONV_INIT; diff --git a/src/refs.h b/src/refs.h index c4786ddb4..80e655af7 100644 --- a/src/refs.h +++ b/src/refs.h @@ -55,7 +55,7 @@ extern bool git_reference__enable_symbolic_ref_target_validation; #define GIT_REFS_STASH_FILE GIT_REFS_DIR GIT_STASH_FILE #define GIT_REF_FORMAT__PRECOMPOSE_UNICODE (1u << 16) -#define GIT_REF_VALIDATION_DISABLE (1u << 15) +#define GIT_REF_FORMAT__VALIDATION_DISABLE (1u << 15) #define GIT_REFNAME_MAX 1024 diff --git a/src/settings.c b/src/settings.c index 1fcdce2ed..bf0477b06 100644 --- a/src/settings.c +++ b/src/settings.c @@ -192,7 +192,7 @@ int git_libgit2_opts(int key, ...) git_object__strict_input_validation = (va_arg(ap, int) != 0); break; - case GIT_OPT_ENABLE_SYMBOLIC_REF_TARGET_VALIDATION: + case GIT_OPT_ENABLE_STRICT_SYMBOLIC_REF_CREATION: git_reference__enable_symbolic_ref_target_validation = (va_arg(ap, int) != 0); break; From 7414acf5f97c0be1fec0504a61624be3eb814f2f Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Mon, 23 Jan 2017 12:28:02 +0000 Subject: [PATCH 046/366] parameter 'id' not found in the function declaration --- include/git2/tree.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/git2/tree.h b/include/git2/tree.h index a38215f9f..4740b1ffa 100644 --- a/include/git2/tree.h +++ b/include/git2/tree.h @@ -381,7 +381,7 @@ GIT_EXTERN(int) git_treebuilder_write( * * @see git_treebuilder_write * - * @param id Pointer to store the OID of the newly written tree + * @param oid Pointer to store the OID of the newly written tree * @param bld Tree builder to write * @param tree Shared buffer for writing the tree. Will be grown as necessary. * @return 0 or an error code From e2b3dc16b904b4989e076ec263da429724e7294b Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Mon, 23 Jan 2017 13:29:47 +0100 Subject: [PATCH 047/366] variable 'i' is used uninitialized whenever 'if' condition is true --- src/submodule.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/submodule.c b/src/submodule.c index 21e3d45e4..e1f59b88e 100644 --- a/src/submodule.c +++ b/src/submodule.c @@ -349,9 +349,10 @@ done: static int submodules_from_index(git_strmap *map, git_index *idx, git_config *cfg) { int error; - git_iterator *i; + git_iterator *i = NULL; const git_index_entry *entry; git_strmap *names = 0; + git_strmap_alloc(&names); if ((error = load_submodule_names(names, cfg))) goto done; From 0fbff82b579ae4bb764a293e9f4ef543c549ba2b Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Sun, 22 Jan 2017 00:30:02 +0000 Subject: [PATCH 048/366] submodule: don't double free during load failure When we fail to load submodules, don't free the list; it is later freed unconditionally. --- src/submodule.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/submodule.c b/src/submodule.c index e1f59b88e..9e007df2b 100644 --- a/src/submodule.c +++ b/src/submodule.c @@ -188,8 +188,7 @@ static int load_submodule_names(git_strmap *out, git_config *cfg) git_buf_put(&buf, fdot + 1, ldot - fdot - 1); git_strmap_insert(out, entry->value, git_buf_detach(&buf), rval); if (rval < 0) { - giterr_set(GITERR_NOMEMORY, "Error inserting submodule into hash table"); - free_submodule_names(out); + giterr_set(GITERR_NOMEMORY, "error inserting submodule into hash table"); return -1; } } From 60c2bf47e40d86f1fcf9b9b928666ed2b06d0e4d Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Sun, 22 Jan 2017 00:58:41 +0000 Subject: [PATCH 049/366] submodule: only examine idx & head given a config --- src/submodule.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/submodule.c b/src/submodule.c index 9e007df2b..fc3dcb406 100644 --- a/src/submodule.c +++ b/src/submodule.c @@ -512,12 +512,12 @@ int git_submodule__map(git_repository *repo, git_strmap *map) goto cleanup; } /* add back submodule information from index */ - if (idx) { + if (mods && idx) { if ((error = submodules_from_index(map, idx, mods)) < 0) goto cleanup; } /* add submodule information from HEAD */ - if (head) { + if (mods && head) { if ((error = submodules_from_head(map, head, mods)) < 0) goto cleanup; } From a0d384798312df3b2c79194ced81bf5a3d2afddc Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Sun, 22 Jan 2017 01:42:45 +0000 Subject: [PATCH 050/366] mac: on 32 bit, use `__builtin_umull_overflow` --- src/integer.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/integer.h b/src/integer.h index b08094c2f..61712cebf 100644 --- a/src/integer.h +++ b/src/integer.h @@ -55,16 +55,16 @@ GIT_INLINE(bool) git__add_uint64_overflow(uint64_t *out, uint64_t one, uint64_t } /* Use clang/gcc compiler intrinsics whenever possible */ -#if (SIZE_MAX == UINT_MAX) && __has_builtin(__builtin_uadd_overflow) -# define git__add_sizet_overflow(out, one, two) \ - __builtin_uadd_overflow(one, two, out) -# define git__multiply_sizet_overflow(out, one, two) \ - __builtin_umul_overflow(one, two, out) -#elif (SIZE_MAX == ULONG_MAX) && __has_builtin(__builtin_uaddl_overflow) +#if (SIZE_MAX == ULONG_MAX) && __has_builtin(__builtin_uaddl_overflow) # define git__add_sizet_overflow(out, one, two) \ __builtin_uaddl_overflow(one, two, out) # define git__multiply_sizet_overflow(out, one, two) \ __builtin_umull_overflow(one, two, out) +#elif (SIZE_MAX == UINT_MAX) && __has_builtin(__builtin_uadd_overflow) +# define git__add_sizet_overflow(out, one, two) \ + __builtin_uadd_overflow(one, two, out) +# define git__multiply_sizet_overflow(out, one, two) \ + __builtin_umul_overflow(one, two, out) #else /** From 7f66a70eec3db66fba3dd4a73d5a0151546d2a2f Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 23 Jan 2017 23:00:00 +0000 Subject: [PATCH 051/366] attr_cache_remove: don't remove given file If `attr_cache_lookup_entry` fails to find the given file, make sure that we do not try to free the given file. --- src/attrcache.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/attrcache.c b/src/attrcache.c index 0ade38c7c..cf0707ef0 100644 --- a/src/attrcache.c +++ b/src/attrcache.c @@ -121,20 +121,22 @@ static int attr_cache_remove(git_attr_cache *cache, git_attr_file *file) { int error = 0; git_attr_file_entry *entry; + git_attr_file *old = NULL; if (!file) return 0; + if ((error = attr_cache_lock(cache)) < 0) return error; if ((entry = attr_cache_lookup_entry(cache, file->entry->path)) != NULL) - file = git__compare_and_swap(&entry->file[file->source], file, NULL); + old = git__compare_and_swap(&entry->file[file->source], file, NULL); attr_cache_unlock(cache); - if (file) { - GIT_REFCOUNT_OWN(file, NULL); - git_attr_file__free(file); + if (old) { + GIT_REFCOUNT_OWN(old, NULL); + git_attr_file__free(old); } return error; From 1f813cf2b8c9b1976cec15014dec8edd854f8e88 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 23 Jan 2017 17:32:13 -0600 Subject: [PATCH 052/366] checkout::tree test: cleanup memory leak --- tests/checkout/tree.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/checkout/tree.c b/tests/checkout/tree.c index c9581fdc5..b3b860c63 100644 --- a/tests/checkout/tree.c +++ b/tests/checkout/tree.c @@ -441,6 +441,7 @@ void test_checkout_tree__pathlist_checkout_ignores_non_matches(void) cl_assert(git_path_exists("testrepo/link_to_new.txt")); cl_assert(git_path_exists("testrepo/new.txt")); + git_object_free(g_object); cl_git_pass(git_revparse_single(&g_object, g_repo, "8496071c1b46c854b31185ea97743be6a8774479")); g_opts.checkout_strategy = @@ -454,10 +455,6 @@ void test_checkout_tree__pathlist_checkout_ignores_non_matches(void) cl_assert(!git_path_exists("testrepo/branch_file.txt")); cl_assert(!git_path_exists("testrepo/link_to_new.txt")); cl_assert(git_path_exists("testrepo/new.txt")); - - git_object_free(g_object); - g_object = NULL; - } void test_checkout_tree__can_disable_pattern_match(void) From d0c418c0bb150cce670bbfd1d9343f91f894125a Mon Sep 17 00:00:00 2001 From: Matthew Plough Date: Fri, 27 Jan 2017 12:49:48 -0500 Subject: [PATCH 053/366] Fix uninitialized variable warning Fix the following warning emitted by clang: [ 16%] Building C object CMakeFiles/libgit2_clar.dir/src/submodule.c.o /Users/mplough/devel/external/libgit2/src/submodule.c:408:6: warning: variable 'i' is used uninitialized whenever 'if' condition is true [-Wsometimes-uninitialized] if ((error = load_submodule_names(names, cfg))) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /Users/mplough/devel/external/libgit2/src/submodule.c:448:20: note: uninitialized use occurs here git_iterator_free(i); ^ /Users/mplough/devel/external/libgit2/src/submodule.c:408:2: note: remove the 'if' if its condition is always false if ((error = load_submodule_names(names, cfg))) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /Users/mplough/devel/external/libgit2/src/submodule.c:404:17: note: initialize the variable 'i' to silence this warning git_iterator *i; ^ = NULL 1 warning generated. --- src/submodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/submodule.c b/src/submodule.c index fc3dcb406..1c17075bf 100644 --- a/src/submodule.c +++ b/src/submodule.c @@ -401,7 +401,7 @@ done: static int submodules_from_head(git_strmap *map, git_tree *head, git_config *cfg) { int error; - git_iterator *i; + git_iterator *i = NULL; const git_index_entry *entry; git_strmap *names = 0; git_strmap_alloc(&names); From 921493cc94fa3542e6f7b2ac218a1163826f7dbc Mon Sep 17 00:00:00 2001 From: Matthew Plough Date: Fri, 27 Jan 2017 14:37:16 -0500 Subject: [PATCH 054/366] Update docs for git_oid_fromstrn and p --- include/git2/oid.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/include/git2/oid.h b/include/git2/oid.h index 8ad51c8ba..aaa678cc0 100644 --- a/include/git2/oid.h +++ b/include/git2/oid.h @@ -50,17 +50,16 @@ GIT_EXTERN(int) git_oid_fromstr(git_oid *out, const char *str); * Parse a hex formatted null-terminated string into a git_oid. * * @param out oid structure the result is written into. - * @param str input hex string; must be at least 4 characters - * long and null-terminated. + * @param str input hex string; must be null-terminated. * @return 0 or an error code */ GIT_EXTERN(int) git_oid_fromstrp(git_oid *out, const char *str); /** - * Parse N characters of a hex formatted object id into a git_oid + * Parse N characters of a hex formatted object id into a git_oid. * - * If N is odd, N-1 characters will be parsed instead. - * The remaining space in the git_oid will be set to zero. + * If N is odd, the last byte's high nibble will be read in and the + * low nibble set to zero. * * @param out oid structure the result is written into. * @param str input hex string of at least size `length` From 39e76bb346760ad1183e8253186df3044752341e Mon Sep 17 00:00:00 2001 From: tyler wanek Date: Fri, 27 Jan 2017 16:05:20 -0700 Subject: [PATCH 055/366] Do not discard proxy_options that have been set when auto is specified --- src/transports/http.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/transports/http.c b/src/transports/http.c index 949e857b0..cb4a6d0d5 100644 --- a/src/transports/http.c +++ b/src/transports/http.c @@ -575,6 +575,9 @@ static int apply_proxy_config(http_subtransport *t) if ((error = git_remote__get_http_proxy(t->owner->owner, !!t->connection_data.use_ssl, &url)) < 0) return error; + opts.credentials = t->owner->proxy.credentials; + opts.certificate_check = t->owner->proxy.certificate_check; + opts.payload = t->owner->proxy.payload; opts.type = GIT_PROXY_SPECIFIED; opts.url = url; error = git_stream_set_proxy(t->io, &opts); From 390431c322b3badf7850a5653c8a126c30f95deb Mon Sep 17 00:00:00 2001 From: Adam Niedzielski Date: Wed, 1 Feb 2017 17:31:31 +0100 Subject: [PATCH 056/366] revwal: add failing test for walking with topo-sort --- tests/revwalk/basic.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/revwalk/basic.c b/tests/revwalk/basic.c index 89140bc54..572035c85 100644 --- a/tests/revwalk/basic.c +++ b/tests/revwalk/basic.c @@ -331,6 +331,20 @@ void test_revwalk_basic__hide_then_push(void) cl_assert_equal_i(i, 0); } +void test_revwalk_basic__topo_crash(void) +{ + git_oid oid; + git_oid_fromstr(&oid, "5b5b025afb0b4c913b4c338a42934a3863bf3644"); + + revwalk_basic_setup_walk(NULL); + git_revwalk_sorting(_walk, GIT_SORT_TOPOLOGICAL); + + cl_git_pass(git_revwalk_push(_walk, &oid)); + cl_git_pass(git_revwalk_hide(_walk, &oid)); + + git_revwalk_next(&oid, _walk); +} + void test_revwalk_basic__push_range(void) { revwalk_basic_setup_walk(NULL); From f47db3c799b4f6b63ee8021e0c93d00d5f125c9a Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Thu, 2 Feb 2017 16:02:57 +0100 Subject: [PATCH 057/366] vector: do not reverse a vector if it is empty The code reversing a vector initially determines the rear-pointer by simply subtracting 1 from the vector's length. Obviously, this fails if the vector is empty, in which case we have an integer overflow. Fix the issue by returning early if the vector is empty. --- src/vector.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vector.c b/src/vector.c index baec8036f..620a1f56c 100644 --- a/src/vector.c +++ b/src/vector.c @@ -406,6 +406,9 @@ void git_vector_reverse(git_vector *v) { size_t a, b; + if (v->length == 0) + return; + a = 0; b = v->length - 1; From 21d4a3783e657c2426511760579e8883b076068f Mon Sep 17 00:00:00 2001 From: Remy Suen Date: Sat, 4 Feb 2017 17:24:31 +0900 Subject: [PATCH 058/366] Flag given_opts in git_revert as optional The given_opts argument can actually be NULL and thus should be flagged accordingly in the header file. --- include/git2/revert.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/git2/revert.h b/include/git2/revert.h index 2de194219..82dbadcfc 100644 --- a/include/git2/revert.h +++ b/include/git2/revert.h @@ -75,7 +75,7 @@ GIT_EXTERN(int) git_revert_commit( * * @param repo the repository to revert * @param commit the commit to revert - * @param given_opts merge flags + * @param given_opts the revert options (or null for defaults) * @return zero on success, -1 on failure. */ GIT_EXTERN(int) git_revert( From 3a133652691c07abb1a898a3704e693cb9c40901 Mon Sep 17 00:00:00 2001 From: Remy Suen Date: Sun, 5 Feb 2017 07:12:32 +0900 Subject: [PATCH 059/366] Flag checkout_opts in git_reset as optional The check_outs argument can be NULL and should be flagged accordingly in the header file. --- include/git2/reset.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/git2/reset.h b/include/git2/reset.h index 79075291f..bd29c69e4 100644 --- a/include/git2/reset.h +++ b/include/git2/reset.h @@ -53,7 +53,7 @@ typedef enum { * * @param reset_type Kind of reset operation to perform. * - * @param checkout_opts Checkout options to be used for a HARD reset. + * @param checkout_opts Optional checkout options to be used for a HARD reset. * The checkout_strategy field will be overridden (based on reset_type). * This parameter can be used to propagate notify and progress callbacks. * From fa2dfcf924f29f9987fa9bd00479601619a4719d Mon Sep 17 00:00:00 2001 From: Chris Bargren Date: Wed, 1 Feb 2017 09:28:30 -0700 Subject: [PATCH 060/366] Fix digest credentials for proxy in windows --- src/transports/winhttp.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c index 0d304d6b3..4f4af0096 100644 --- a/src/transports/winhttp.c +++ b/src/transports/winhttp.c @@ -70,6 +70,7 @@ typedef enum { GIT_WINHTTP_AUTH_BASIC = 1, GIT_WINHTTP_AUTH_NTLM = 2, GIT_WINHTTP_AUTH_NEGOTIATE = 4, + GIT_WINHTTP_AUTH_DIGEST = 8, } winhttp_authmechanism_t; typedef struct { @@ -131,8 +132,13 @@ done: return error; } -static int apply_userpass_credential_proxy(HINTERNET request, git_cred *cred) +static int apply_userpass_credential_proxy(HINTERNET request, git_cred *cred, int mechanisms) { + if (GIT_WINHTTP_AUTH_DIGEST & mechanisms) { + return _apply_userpass_credential(request, WINHTTP_AUTH_TARGET_PROXY, + WINHTTP_AUTH_SCHEME_DIGEST, cred); + } + return _apply_userpass_credential(request, WINHTTP_AUTH_TARGET_PROXY, WINHTTP_AUTH_SCHEME_BASIC, cred); } @@ -451,7 +457,7 @@ static int winhttp_stream_connect(winhttp_stream *s) if (t->proxy_cred) { if (t->proxy_cred->credtype == GIT_CREDTYPE_USERPASS_PLAINTEXT) { - if ((error = apply_userpass_credential_proxy(s->request, t->proxy_cred)) < 0) + if ((error = apply_userpass_credential_proxy(s->request, t->proxy_cred, t->auth_mechanisms)) < 0) goto on_error; } } @@ -588,11 +594,11 @@ static int parse_unauthorized_response( *allowed_types = 0; *allowed_mechanisms = 0; - /* WinHttpQueryHeaders() must be called before WinHttpQueryAuthSchemes(). - * We can assume this was already done, since we know we are unauthorized. + /* WinHttpQueryHeaders() must be called before WinHttpQueryAuthSchemes(). + * We can assume this was already done, since we know we are unauthorized. */ if (!WinHttpQueryAuthSchemes(request, &supported, &first, &target)) { - giterr_set(GITERR_OS, "failed to parse supported auth schemes"); + giterr_set(GITERR_OS, "failed to parse supported auth schemes"); return -1; } @@ -612,6 +618,11 @@ static int parse_unauthorized_response( *allowed_mechanisms |= GIT_WINHTTP_AUTH_BASIC; } + if (WINHTTP_AUTH_SCHEME_DIGEST & supported) { + *allowed_types |= GIT_CREDTYPE_USERPASS_PLAINTEXT; + *allowed_mechanisms |= GIT_WINHTTP_AUTH_DIGEST; + } + return 0; } @@ -783,7 +794,7 @@ static int winhttp_connect( goto on_error; } - + /* Establish connection */ t->connection = WinHttpConnect( t->session, @@ -863,7 +874,7 @@ static int send_request(winhttp_stream *s, size_t len, int ignore_length) return 0; ignore_flags = no_check_cert_flags; - + if (!WinHttpSetOption(s->request, WINHTTP_OPTION_SECURITY_FLAGS, &ignore_flags, sizeof(ignore_flags))) { giterr_set(GITERR_OS, "failed to set security options"); return -1; From 1e929eb5e20b10658709e3d28d109d56b3fb3c3d Mon Sep 17 00:00:00 2001 From: Christopher Bargren Date: Mon, 6 Feb 2017 11:00:06 -0700 Subject: [PATCH 061/366] Pass proxy options payload to credentials callback --- src/transports/winhttp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c index 4f4af0096..ae41725a7 100644 --- a/src/transports/winhttp.c +++ b/src/transports/winhttp.c @@ -1083,7 +1083,7 @@ replay: /* TODO: extract the username from the url, no payload? */ if (t->owner->proxy.credentials) { int cred_error = 1; - cred_error = t->owner->proxy.credentials(&t->proxy_cred, t->owner->proxy.url, NULL, allowed_types, NULL); + cred_error = t->owner->proxy.credentials(&t->proxy_cred, t->owner->proxy.url, NULL, allowed_types, t->owner->proxy.payload); if (cred_error < 0) return cred_error; From d8c06070a87ced23712eaa2b55a0cebb148f9f9a Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Tue, 7 Feb 2017 20:21:38 +0100 Subject: [PATCH 062/366] path: extract `win32_path_prefix` function Extract code which determines if a path is at a Windows system's root. This incluses drive prefixes (e.g. "C:\") as well as network computer names (e.g. "//computername/"). --- src/path.c | 56 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/src/path.c b/src/path.c index bffde930b..0e9e04d72 100644 --- a/src/path.c +++ b/src/path.c @@ -110,6 +110,34 @@ Exit: return result; } +/* + * Determine if the path is a Windows prefix and, if so, returns + * its actual lentgh. If it is not a prefix, returns -1. + */ +static int win32_prefix_length(const char *path, int len) +{ +#ifndef GIT_WIN32 + GIT_UNUSED(path); + GIT_UNUSED(len); +#else + /* + * Mimic unix behavior where '/.git' returns '/': 'C:/.git' will return + * 'C:/' here + */ + if (len == 2 && LOOKS_LIKE_DRIVE_PREFIX(path)) + return 3; + + /* + * Similarly checks if we're dealing with a network computer name + * '//computername/.git' will return '//computername/' + */ + if (looks_like_network_computer_name(path, len)) + return len + 1; +#endif + + return -1; +} + /* * Based on the Android implementation, BSD licensed. * Check http://android.git.kernel.org/ @@ -117,7 +145,7 @@ Exit: int git_path_dirname_r(git_buf *buffer, const char *path) { const char *endp; - int result, len; + int len; /* Empty or NULL string gets treated as "." */ if (path == NULL || *path == '\0') { @@ -146,35 +174,17 @@ int git_path_dirname_r(git_buf *buffer, const char *path) endp--; } while (endp > path && *endp == '/'); + if ((len = win32_prefix_length(path, endp - path + 1)) > 0) + goto Exit; + /* Cast is safe because max path < max int */ len = (int)(endp - path + 1); -#ifdef GIT_WIN32 - /* Mimic unix behavior where '/.git' returns '/': 'C:/.git' will return - 'C:/' here */ - - if (len == 2 && LOOKS_LIKE_DRIVE_PREFIX(path)) { - len = 3; - goto Exit; - } - - /* Similarly checks if we're dealing with a network computer name - '//computername/.git' will return '//computername/' */ - - if (looks_like_network_computer_name(path, len)) { - len++; - goto Exit; - } - -#endif - Exit: - result = len; - if (buffer != NULL && git_buf_set(buffer, path, len) < 0) return -1; - return result; + return len; } From 5d59520ccd4816080e68b5a3057653c15f3d6816 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Tue, 7 Feb 2017 20:30:11 +0100 Subject: [PATCH 063/366] path: get correct dirname for Windows root Getting the dirname of a filesystem root should return the filesystem root itself. E.g. the dirname of "/" is always "/". On Windows, we emulate this behavior and as such, we should return e.g. "C:/" if calling dirname on "C:/". But we currently fail to do so and instead return ".", as we do not check if we actually have a Windows prefix before stripping off the last directory component. Fix this by calling out to `win32_prefix_length` immediately after stripping trailing slashes, returning early if we have a prefix. --- src/path.c | 3 +++ tests/core/path.c | 2 ++ 2 files changed, 5 insertions(+) diff --git a/src/path.c b/src/path.c index 0e9e04d72..3c78c8b7c 100644 --- a/src/path.c +++ b/src/path.c @@ -159,6 +159,9 @@ int git_path_dirname_r(git_buf *buffer, const char *path) while (endp > path && *endp == '/') endp--; + if ((len = win32_prefix_length(path, endp - path + 1)) > 0) + goto Exit; + /* Find the start of the dir */ while (endp > path && *endp != '/') endp--; diff --git a/tests/core/path.c b/tests/core/path.c index 71c6eda58..eaaaf7245 100644 --- a/tests/core/path.c +++ b/tests/core/path.c @@ -89,8 +89,10 @@ void test_core_path__00_dirname(void) check_dirname(REP16("/abc"), REP15("/abc")); #ifdef GIT_WIN32 + check_dirname("C:/", "C:/"); check_dirname("C:/path/", "C:/"); check_dirname("C:/path", "C:/"); + check_dirname("//computername/", "//computername/"); check_dirname("//computername/path/", "//computername/"); check_dirname("//computername/path", "//computername/"); check_dirname("//computername/sub/path/", "//computername/sub"); From 9e8d75c7d447531d81133bf880c1a5f45a45c340 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 8 Feb 2017 11:41:10 +0100 Subject: [PATCH 064/366] path: ensure dirname on Win32 prefix always has a trailing '/' When calling `git_path_dirname_r` on a Win32 prefix, e.g. a drive or network share prefix, we always want to return the trailing '/'. This does not work currently when passing in a path like 'C:', where the '/' would not be appended correctly. Fix this by appending a '/' if we try to normalize a Win32 prefix and there is no trailing '/'. --- src/path.c | 22 +++++++++++++++------- tests/core/path.c | 2 ++ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/path.c b/src/path.c index 3c78c8b7c..c3d3eb1ce 100644 --- a/src/path.c +++ b/src/path.c @@ -125,14 +125,14 @@ static int win32_prefix_length(const char *path, int len) * 'C:/' here */ if (len == 2 && LOOKS_LIKE_DRIVE_PREFIX(path)) - return 3; + return 2; /* * Similarly checks if we're dealing with a network computer name * '//computername/.git' will return '//computername/' */ if (looks_like_network_computer_name(path, len)) - return len + 1; + return len; #endif return -1; @@ -145,7 +145,7 @@ static int win32_prefix_length(const char *path, int len) int git_path_dirname_r(git_buf *buffer, const char *path) { const char *endp; - int len; + int is_prefix = 0, len; /* Empty or NULL string gets treated as "." */ if (path == NULL || *path == '\0') { @@ -159,8 +159,10 @@ int git_path_dirname_r(git_buf *buffer, const char *path) while (endp > path && *endp == '/') endp--; - if ((len = win32_prefix_length(path, endp - path + 1)) > 0) + if ((len = win32_prefix_length(path, endp - path + 1)) > 0) { + is_prefix = 1; goto Exit; + } /* Find the start of the dir */ while (endp > path && *endp != '/') @@ -177,15 +179,21 @@ int git_path_dirname_r(git_buf *buffer, const char *path) endp--; } while (endp > path && *endp == '/'); - if ((len = win32_prefix_length(path, endp - path + 1)) > 0) + if ((len = win32_prefix_length(path, endp - path + 1)) > 0) { + is_prefix = 1; goto Exit; + } /* Cast is safe because max path < max int */ len = (int)(endp - path + 1); Exit: - if (buffer != NULL && git_buf_set(buffer, path, len) < 0) - return -1; + if (buffer) { + if (git_buf_set(buffer, path, len) < 0) + return -1; + if (is_prefix && git_buf_putc(buffer, '/') < 0) + return -1; + } return len; } diff --git a/tests/core/path.c b/tests/core/path.c index eaaaf7245..fefe2aeac 100644 --- a/tests/core/path.c +++ b/tests/core/path.c @@ -90,9 +90,11 @@ void test_core_path__00_dirname(void) #ifdef GIT_WIN32 check_dirname("C:/", "C:/"); + check_dirname("C:", "C:/"); check_dirname("C:/path/", "C:/"); check_dirname("C:/path", "C:/"); check_dirname("//computername/", "//computername/"); + check_dirname("//computername", "//computername/"); check_dirname("//computername/path/", "//computername/"); check_dirname("//computername/path", "//computername/"); check_dirname("//computername/sub/path/", "//computername/sub"); From 3428a523597a75127bf258b6d74c2871df5e8f0d Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 8 Feb 2017 12:02:32 +0100 Subject: [PATCH 065/366] tests: repo: assert discovery starting at Win32 roots finishes As of recently, we failed to correctly discover repositories at a Win32 system root. Instead of aborting the upwards-traversal of the file system, we were looping infinitely when traversal started at either a Win32 drive prefix ("C:/") or a network path ("//somehost"). The issue has been fixed, so add a test to catch regressions. --- tests/repo/discover.c | 9 +++++++++ tests/resources/testrepo.git/index | Bin 2 files changed, 9 insertions(+) mode change 100644 => 100755 tests/resources/testrepo.git/index diff --git a/tests/repo/discover.c b/tests/repo/discover.c index 48aa27581..abb7bd12b 100644 --- a/tests/repo/discover.c +++ b/tests/repo/discover.c @@ -199,3 +199,12 @@ void test_repo_discover__discovery_starting_at_file_succeeds(void) ensure_repository_discover(SUB_REPOSITORY_FOLDER "/file", ceiling_dirs.ptr, SUB_REPOSITORY_GITDIR); } + +void test_repo_discover__discovery_starting_at_system_root_causes_no_hang(void) +{ +#ifdef GIT_WIN32 + git_buf out = GIT_BUF_INIT; + cl_git_fail(git_repository_discover(&out, "C:/", 0, NULL)); + cl_git_fail(git_repository_discover(&out, "//localhost/", 0, NULL)); +#endif +} diff --git a/tests/resources/testrepo.git/index b/tests/resources/testrepo.git/index old mode 100644 new mode 100755 From 5f3276c7e66fe54b0485da2def84a6ae322cce59 Mon Sep 17 00:00:00 2001 From: Christopher Bargren Date: Tue, 7 Feb 2017 16:33:28 -0700 Subject: [PATCH 066/366] Add support for lowercase proxy environment variables curl supports HTTPS_PROXY in addition to https_proxy (and their http counterparts). This change ensures parity with curl's behavior. --- src/remote.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/remote.c b/src/remote.c index 8da7346fb..1f5c58bd2 100644 --- a/src/remote.c +++ b/src/remote.c @@ -773,6 +773,18 @@ int git_remote__get_http_proxy(git_remote *remote, bool use_ssl, char **proxy_ur /* HTTP_PROXY / HTTPS_PROXY environment variables */ error = git__getenv(&val, use_ssl ? "HTTPS_PROXY" : "HTTP_PROXY"); + if (error < 0) { + if (error != GIT_ENOTFOUND) { + return error; + } + + giterr_clear(); + error = 0; + } + + /* try lowercase environment variables */ + error = git__getenv(&val, use_ssl ? "https_proxy" : "http_proxy"); + if (error < 0) { if (error == GIT_ENOTFOUND) { giterr_clear(); From 2af282d835662fce671cc1a6675b0b8292f05173 Mon Sep 17 00:00:00 2001 From: Christopher Bargren Date: Wed, 8 Feb 2017 15:01:30 -0700 Subject: [PATCH 067/366] Addressing PR feedback --- src/remote.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/remote.c b/src/remote.c index 1f5c58bd2..808ca78d5 100644 --- a/src/remote.c +++ b/src/remote.c @@ -770,21 +770,14 @@ int git_remote__get_http_proxy(git_remote *remote, bool use_ssl, char **proxy_ur goto found; } - /* HTTP_PROXY / HTTPS_PROXY environment variables */ - error = git__getenv(&val, use_ssl ? "HTTPS_PROXY" : "HTTP_PROXY"); - - if (error < 0) { - if (error != GIT_ENOTFOUND) { - return error; - } - - giterr_clear(); - error = 0; - } - - /* try lowercase environment variables */ + /* http_proxy / https_proxy environment variables */ error = git__getenv(&val, use_ssl ? "https_proxy" : "http_proxy"); + if (error == GIT_ENOTFOUND) { + /* try uppercase environment variables */ + error = git__getenv(&val, use_ssl ? "HTTPS_PROXY" : "HTTP_PROXY"); + } + if (error < 0) { if (error == GIT_ENOTFOUND) { giterr_clear(); From 93e2c74493cebb4503b8af793d4150b528efbdf5 Mon Sep 17 00:00:00 2001 From: Remy Suen Date: Thu, 9 Feb 2017 19:12:31 +0900 Subject: [PATCH 068/366] Flag optional parameters for apply and pop The options parameter in both git_stash_apply and git_stash_pop can be NULL. They should be flagged as such in the documentation. --- include/git2/stash.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/git2/stash.h b/include/git2/stash.h index 733d75a7f..3af9cde38 100644 --- a/include/git2/stash.h +++ b/include/git2/stash.h @@ -173,7 +173,7 @@ GIT_EXTERN(int) git_stash_apply_init_options( * @param repo The owning repository. * @param index The position within the stash list. 0 points to the * most recent stashed state. - * @param options Options to control how stashes are applied. + * @param options Optional options to control how stashes are applied. * * @return 0 on success, GIT_ENOTFOUND if there's no stashed state for the * given index, GIT_EMERGECONFLICT if changes exist in the working @@ -242,7 +242,7 @@ GIT_EXTERN(int) git_stash_drop( * @param repo The owning repository. * @param index The position within the stash list. 0 points to the * most recent stashed state. - * @param options Options to control how stashes are applied. + * @param options Optional options to control how stashes are applied. * * @return 0 on success, GIT_ENOTFOUND if there's no stashed state for the given * index, or error code. (see git_stash_apply() above for details) From 49806e9bc4650ec1112246292fcfe3941eb99268 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 9 Feb 2017 16:52:03 +0000 Subject: [PATCH 069/366] merge_trees: introduce test for submodule renames Test that shows that submodules are incorrectly considered in renames, and `git_merge_trees` will fail to lookup the submodule as a blob. --- tests/merge/trees/renames.c | 22 ++++++++++++++++++ .../2a/f2d9bcbc73723ac988bb202d4397f72a6ca7a0 | Bin 0 -> 105 bytes .../37/f53a5a14f64e91089a39ea58e71c87d81df765 | Bin 0 -> 173 bytes .../4d/d1ef7569b18d92d93c0a35bb6b93049137b355 | Bin 0 -> 30 bytes .../63/ec604d491161ddafdae4179843c26d54bd999a | Bin 0 -> 30 bytes .../68/f7c02064019d89e40e51d7776b6f67914420a2 | Bin 0 -> 105 bytes .../94/29c05dd6f6f39fc567b4ce923b16df5d3d7a7a | Bin 0 -> 94 bytes .../a1/07e18a58f38c46086c8f8f1dcd54c40154eeb6 | Bin 0 -> 138 bytes .../a2/d8d1824c68541cca94ffb90f79291eba495921 | Bin 0 -> 30 bytes .../bc/85d1aad435ff3705a8c30ace85f7542c5736cb | Bin 0 -> 104 bytes .../c8/26ef8b17b5cd2c4a0023f265f3a423b3aa0388 | Bin 0 -> 157 bytes .../cd/3e8d4aa06bdc781f264171030bc28f2b370fee | Bin 0 -> 94 bytes .../e2/6b8888956137218d8589368a3e606cf50fbb56 | Bin 0 -> 105 bytes .../e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 | Bin 0 -> 15 bytes .../f9/7da95f156121bea8f978623628f4cbdbf30b36 | Bin 0 -> 159 bytes .../.gitted/refs/heads/submodule_rename1 | Bin 0 -> 41 bytes .../.gitted/refs/heads/submodule_rename2 | Bin 0 -> 41 bytes 17 files changed, 22 insertions(+) create mode 100644 tests/resources/merge-resolve/.gitted/objects/2a/f2d9bcbc73723ac988bb202d4397f72a6ca7a0 create mode 100644 tests/resources/merge-resolve/.gitted/objects/37/f53a5a14f64e91089a39ea58e71c87d81df765 create mode 100644 tests/resources/merge-resolve/.gitted/objects/4d/d1ef7569b18d92d93c0a35bb6b93049137b355 create mode 100644 tests/resources/merge-resolve/.gitted/objects/63/ec604d491161ddafdae4179843c26d54bd999a create mode 100644 tests/resources/merge-resolve/.gitted/objects/68/f7c02064019d89e40e51d7776b6f67914420a2 create mode 100644 tests/resources/merge-resolve/.gitted/objects/94/29c05dd6f6f39fc567b4ce923b16df5d3d7a7a create mode 100644 tests/resources/merge-resolve/.gitted/objects/a1/07e18a58f38c46086c8f8f1dcd54c40154eeb6 create mode 100644 tests/resources/merge-resolve/.gitted/objects/a2/d8d1824c68541cca94ffb90f79291eba495921 create mode 100644 tests/resources/merge-resolve/.gitted/objects/bc/85d1aad435ff3705a8c30ace85f7542c5736cb create mode 100644 tests/resources/merge-resolve/.gitted/objects/c8/26ef8b17b5cd2c4a0023f265f3a423b3aa0388 create mode 100644 tests/resources/merge-resolve/.gitted/objects/cd/3e8d4aa06bdc781f264171030bc28f2b370fee create mode 100644 tests/resources/merge-resolve/.gitted/objects/e2/6b8888956137218d8589368a3e606cf50fbb56 create mode 100644 tests/resources/merge-resolve/.gitted/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 create mode 100644 tests/resources/merge-resolve/.gitted/objects/f9/7da95f156121bea8f978623628f4cbdbf30b36 create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/submodule_rename1 create mode 100644 tests/resources/merge-resolve/.gitted/refs/heads/submodule_rename2 diff --git a/tests/merge/trees/renames.c b/tests/merge/trees/renames.c index 6f5c36b0a..853bf2fa0 100644 --- a/tests/merge/trees/renames.c +++ b/tests/merge/trees/renames.c @@ -252,3 +252,25 @@ void test_merge_trees_renames__no_rename_index(void) git_index_free(index); } + +void test_merge_trees_renames__submodules(void) +{ + git_index *index; + git_merge_options *opts = NULL; + + struct merge_index_entry merge_index_entries[] = { + { 0100644, "cd3e8d4aa06bdc781f264171030bc28f2b370fee", 0, ".gitmodules" }, + { 0100644, "4dd1ef7569b18d92d93c0a35bb6b93049137b355", 1, "file.txt" }, + { 0100644, "a2d8d1824c68541cca94ffb90f79291eba495921", 2, "file.txt" }, + { 0100644, "63ec604d491161ddafdae4179843c26d54bd999a", 3, "file.txt" }, + { 0160000, "0000000000000000000000000000000000000001", 1, "submodule1" }, + { 0160000, "0000000000000000000000000000000000000002", 3, "submodule1" }, + { 0160000, "0000000000000000000000000000000000000003", 0, "submodule2" }, + }; + + cl_git_pass(merge_trees_from_branches(&index, repo, + "submodule_rename1", "submodule_rename2", + opts)); + cl_assert(merge_test_index(index, merge_index_entries, 7)); + git_index_free(index); +} diff --git a/tests/resources/merge-resolve/.gitted/objects/2a/f2d9bcbc73723ac988bb202d4397f72a6ca7a0 b/tests/resources/merge-resolve/.gitted/objects/2a/f2d9bcbc73723ac988bb202d4397f72a6ca7a0 new file mode 100644 index 0000000000000000000000000000000000000000..0d658237b4ba290bb240ac5d9c1ff527a89e1741 GIT binary patch literal 105 zcmV-v0G9uF0V^p=O;s>7G-fa~FfcPQQP4}zEXmDJDa}bOW|*RRAokj~&-0I_Z#g%~ zTI_zTZB-RiSz2aJs$NM&34`y&_obN|dnetr;WFKwJ(*>q`Q}hVGXo${C@xKcm}JO+ L1uy~t!KWs;EQ2k& literal 0 HcmV?d00001 diff --git a/tests/resources/merge-resolve/.gitted/objects/37/f53a5a14f64e91089a39ea58e71c87d81df765 b/tests/resources/merge-resolve/.gitted/objects/37/f53a5a14f64e91089a39ea58e71c87d81df765 new file mode 100644 index 0000000000000000000000000000000000000000..95327ed646a2eba6ea6300c37a1d263d958f1c59 GIT binary patch literal 173 zcmV;e08;;W0hNwHYC|y$M7#DWv=0>7k!5`dB@lXpUcld$<1GGna2;~}I*Q!X znbfxJHozUj$LOlSQbIz9OlX%ZixR50IfTF~7Y>Uhau}Vt$FBQ;Xfddj=%pMb5uuuD>`kC7H1(t-_&n*WBoH8?= bFNgk7G-fa~FfcPQQP4}zEXmDJDa}bOW|*RRAokj~&-0I_Z#g%~ zTI_zTZB-RiSz2aJs$NM&2}AOm1Yb|V#JlTnJrSSbd?+_$@61_-W(Gi@P+Xb>G0Bht L3t$2O+MFkY^RX-m literal 0 HcmV?d00001 diff --git a/tests/resources/merge-resolve/.gitted/objects/94/29c05dd6f6f39fc567b4ce923b16df5d3d7a7a b/tests/resources/merge-resolve/.gitted/objects/94/29c05dd6f6f39fc567b4ce923b16df5d3d7a7a new file mode 100644 index 0000000000000000000000000000000000000000..d4d93f508ab6fc65950f32f421195b5807187be1 GIT binary patch literal 94 zcmV-k0HObQ0ZYosPg1ZnV~8#;P0GzrDa}b$P=YfJm14O#3ld8*6l@g`f?S-XML9r` zjFOUqVk>?9^vsfs(j>j){9OH<%p@SsNIxXCxWqlPBq+5Yzc{lbzo?Q605*3d5oL`i Au>b%7 literal 0 HcmV?d00001 diff --git a/tests/resources/merge-resolve/.gitted/objects/a1/07e18a58f38c46086c8f8f1dcd54c40154eeb6 b/tests/resources/merge-resolve/.gitted/objects/a1/07e18a58f38c46086c8f8f1dcd54c40154eeb6 new file mode 100644 index 0000000000000000000000000000000000000000..598c6a7a6186514b0253e8d82027a523326d64c6 GIT binary patch literal 138 zcmV;50CoR(0iBIY3IZ_@1zqP9y%!{t#C%{7H!j?JfzD@~29rQ0qt`cH!CE~E9u;cN z)M2vj&|69%a1qh@;DeDyNDR(e?*$i8NoN)#PzN-~8SZ_p4Q}y+Ey821d8-BHH0*C( spVZggpF+(Sn3UD}Y^+vrlpWO>}!WXpkrj2T0U&#zVNc)yRUjP6A literal 0 HcmV?d00001 diff --git a/tests/resources/merge-resolve/.gitted/objects/a2/d8d1824c68541cca94ffb90f79291eba495921 b/tests/resources/merge-resolve/.gitted/objects/a2/d8d1824c68541cca94ffb90f79291eba495921 new file mode 100644 index 0000000000000000000000000000000000000000..2d3d947184506754e5bf5963da79aecbf5243b3d GIT binary patch literal 30 mcmb7G-fa~FfcPQQP4}zEXmDJDa}bOW;kot>$M>JPKCUhV<9v5 zp?+<1{&!GiX_+~xdL8*ktR^65AOW+E|z*Ee3lT0II1UaY08 zT^a+2-k2pD3^bSlwVjNnL_o7e@|ICy%%E}zfa2vFZ(Vw=Cf4MEvZd%y5k|_Cb&3gG zbV`F`4k-NIm)hhleSAyuzSQ!rn>_Qdzjb}Aec8h))^d^B5h6^pHu9(jV%YJr^S`~w L>yyP7U~WeMr&~-} literal 0 HcmV?d00001 diff --git a/tests/resources/merge-resolve/.gitted/objects/cd/3e8d4aa06bdc781f264171030bc28f2b370fee b/tests/resources/merge-resolve/.gitted/objects/cd/3e8d4aa06bdc781f264171030bc28f2b370fee new file mode 100644 index 0000000000000000000000000000000000000000..144225df1f2f40f321360fcac0ebcf9b8ef0b560 GIT binary patch literal 94 zcmV-k0HObQ0ZYosPg1ZnV~8#;P0GzrDa}b$P=Yg!lw!F!3ld8*6l@g`f?S-XML9r` zjFOUqVk>?9^vsfs(j>j){9OH<%p@SsNIxXCxWqlPBq+5Yzc{lbzo?Q6057G-fa~FfcPQQP4}zEXmDJDa}bOW|*RRAokj~&-0I_Z#g%~ zTI_zTZB-RiSz2aJs$NM&2}AOm1Yb|V#JlTnJrSSbd?+_$@61_-W(Gi@P+Xb>G0Bht L3t$8Q+M6eW^SLYu literal 0 HcmV?d00001 diff --git a/tests/resources/merge-resolve/.gitted/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 b/tests/resources/merge-resolve/.gitted/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 new file mode 100644 index 0000000000000000000000000000000000000000..711223894375fe1186ac5bfffdc48fb1fa1e65cc GIT binary patch literal 15 Wcmb Date: Thu, 9 Feb 2017 16:57:22 +0000 Subject: [PATCH 070/366] merge: don't do rename detection on submodules --- src/merge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/merge.c b/src/merge.c index 087178ace..eceadf08a 100644 --- a/src/merge.c +++ b/src/merge.c @@ -1075,7 +1075,7 @@ static int index_entry_similarity_inexact( int score = 0; int error = 0; - if (GIT_MODE_TYPE(a->mode) != GIT_MODE_TYPE(b->mode)) + if (!GIT_MODE_ISBLOB(a->mode) || !GIT_MODE_ISBLOB(b->mode)) return 0; /* update signature cache if needed */ From 191474a1f423aaea6f0b9dacf68216b3ba8e34d4 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 9 Feb 2017 18:28:19 +0000 Subject: [PATCH 071/366] diff: don't do rename detection on submodules --- src/diff_tform.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/diff_tform.c b/src/diff_tform.c index f2ff147d1..b004ddd66 100644 --- a/src/diff_tform.c +++ b/src/diff_tform.c @@ -553,8 +553,8 @@ static int similarity_measure( *score = -1; - /* don't try to compare files of different types */ - if (GIT_MODE_TYPE(a_file->mode) != GIT_MODE_TYPE(b_file->mode)) + /* don't try to compare things that aren't files */ + if (!GIT_MODE_ISBLOB(a_file->mode) || !GIT_MODE_ISBLOB(b_file->mode)) return 0; /* if exact match is requested, force calculation of missing OIDs now */ From 61acc9fadebe895439a19b63074da03ed65b9bd8 Mon Sep 17 00:00:00 2001 From: Gaurav Saral Date: Wed, 8 Feb 2017 16:22:44 +0530 Subject: [PATCH 072/366] Changes to provide option to turn off/on ofs_delta This change provides an option in git_libgit2_opt_t which can be used in git_libgit2_opts to turn off/on ofs_delta capability in libGit2 --- include/git2/common.h | 11 +++++++++++ src/settings.c | 5 +++++ src/transports/smart.h | 2 ++ src/transports/smart_protocol.c | 4 +++- 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/include/git2/common.h b/include/git2/common.h index 5be7fb632..f13dfd509 100644 --- a/include/git2/common.h +++ b/include/git2/common.h @@ -178,6 +178,7 @@ typedef enum { GIT_OPT_ENABLE_STRICT_SYMBOLIC_REF_CREATION, GIT_OPT_SET_SSL_CIPHERS, GIT_OPT_GET_USER_AGENT, + GIT_OPT_ENABLE_OFS_DELTA, } git_libgit2_opt_t; /** @@ -305,6 +306,16 @@ typedef enum { * > * > - `ciphers` is the list of ciphers that are eanbled. * + * * opts(GIT_OPT_ENABLE_OFS_DELTA, int enabled) + * + * > Enable or disable the use of "offset deltas" when creating packfiles, + * > and the negotiation of them when talking to a remote server. + * > Offset deltas store a delta base location as an offset into the + * > packfile from the current location, which provides a shorter encoding + * > and thus smaller resultant packfiles. + * > Packfiles containing offset deltas can still be read. + * > This defaults to enabled. + * * @param option Option key * @param ... value to set the option * @return 0 on success, <0 on failure diff --git a/src/settings.c b/src/settings.c index 222bd6b8e..21585672c 100644 --- a/src/settings.c +++ b/src/settings.c @@ -16,6 +16,7 @@ #include "global.h" #include "object.h" #include "refs.h" +#include "transports/smart.h" void git_libgit2_version(int *major, int *minor, int *rev) { @@ -222,6 +223,10 @@ int git_libgit2_opts(int key, ...) } break; + case GIT_OPT_ENABLE_OFS_DELTA: + git_smart__ofs_delta_enabled = (va_arg(ap, int) != 0); + break; + default: giterr_set(GITERR_INVALID, "invalid option key"); error = -1; diff --git a/src/transports/smart.h b/src/transports/smart.h index 0a0c3fc1b..b47001fe0 100644 --- a/src/transports/smart.h +++ b/src/transports/smart.h @@ -26,6 +26,8 @@ #define GIT_CAP_THIN_PACK "thin-pack" #define GIT_CAP_SYMREF "symref" +extern bool git_smart__ofs_delta_enabled; + enum git_pkt_type { GIT_PKT_CMD, GIT_PKT_FLUSH, diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c index 7a1d4dc14..25e78c65a 100644 --- a/src/transports/smart_protocol.c +++ b/src/transports/smart_protocol.c @@ -19,6 +19,8 @@ /* The minimal interval between progress updates (in seconds). */ #define MIN_PROGRESS_UPDATE_INTERVAL 0.5 +bool git_smart__ofs_delta_enabled = true; + int git_smart__store_refs(transport_smart *t, int flushes) { gitno_buffer *buf = &t->buffer; @@ -138,7 +140,7 @@ int git_smart__detect_caps(git_pkt_ref *pkt, transport_smart_caps *caps, git_vec if (*ptr == ' ') ptr++; - if (!git__prefixcmp(ptr, GIT_CAP_OFS_DELTA)) { + if (git_smart__ofs_delta_enabled && !git__prefixcmp(ptr, GIT_CAP_OFS_DELTA)) { caps->common = caps->ofs_delta = 1; ptr += strlen(GIT_CAP_OFS_DELTA); continue; From 61189a115bb347c9131224ae985fdefa073ef946 Mon Sep 17 00:00:00 2001 From: Christopher Bargren Date: Fri, 10 Feb 2017 07:59:22 -0700 Subject: [PATCH 073/366] Fixing a code style issue --- src/remote.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/remote.c b/src/remote.c index 808ca78d5..d3132f75c 100644 --- a/src/remote.c +++ b/src/remote.c @@ -773,10 +773,9 @@ int git_remote__get_http_proxy(git_remote *remote, bool use_ssl, char **proxy_ur /* http_proxy / https_proxy environment variables */ error = git__getenv(&val, use_ssl ? "https_proxy" : "http_proxy"); - if (error == GIT_ENOTFOUND) { - /* try uppercase environment variables */ + /* try uppercase environment variables */ + if (error == GIT_ENOTFOUND) error = git__getenv(&val, use_ssl ? "HTTPS_PROXY" : "HTTP_PROXY"); - } if (error < 0) { if (error == GIT_ENOTFOUND) { From bd9f4fd24cd9f011dc5105d6f24ea90dfdf4f1b3 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 11 Nov 2015 10:54:08 +0100 Subject: [PATCH 074/366] tests: add worktree test data --- tests/iterator/workdir.c | 3 ++- tests/refs/list.c | 4 ++-- tests/resources/testrepo-worktree/.gitted | Bin 0 -> 53 bytes tests/resources/testrepo-worktree/README | Bin 0 -> 10 bytes tests/resources/testrepo-worktree/branch_file.txt | Bin 0 -> 8 bytes tests/resources/testrepo-worktree/link_to_new.txt | 1 + tests/resources/testrepo-worktree/new.txt | Bin 0 -> 12 bytes .../.gitted/logs/refs/heads/testrepo-worktree | Bin 0 -> 156 bytes .../testrepo/.gitted/refs/heads/testrepo-worktree | Bin 0 -> 41 bytes .../.gitted/worktrees/testrepo-worktree/HEAD | Bin 0 -> 34 bytes .../.gitted/worktrees/testrepo-worktree/commondir | Bin 0 -> 6 bytes .../.gitted/worktrees/testrepo-worktree/gitdir | Bin 0 -> 35 bytes .../.gitted/worktrees/testrepo-worktree/index | Bin 0 -> 369 bytes .../.gitted/worktrees/testrepo-worktree/logs/HEAD | Bin 0 -> 214 bytes 14 files changed, 5 insertions(+), 3 deletions(-) create mode 100644 tests/resources/testrepo-worktree/.gitted create mode 100644 tests/resources/testrepo-worktree/README create mode 100644 tests/resources/testrepo-worktree/branch_file.txt create mode 120000 tests/resources/testrepo-worktree/link_to_new.txt create mode 100644 tests/resources/testrepo-worktree/new.txt create mode 100644 tests/resources/testrepo/.gitted/logs/refs/heads/testrepo-worktree create mode 100644 tests/resources/testrepo/.gitted/refs/heads/testrepo-worktree create mode 100644 tests/resources/testrepo/.gitted/worktrees/testrepo-worktree/HEAD create mode 100644 tests/resources/testrepo/.gitted/worktrees/testrepo-worktree/commondir create mode 100644 tests/resources/testrepo/.gitted/worktrees/testrepo-worktree/gitdir create mode 100644 tests/resources/testrepo/.gitted/worktrees/testrepo-worktree/index create mode 100644 tests/resources/testrepo/.gitted/worktrees/testrepo-worktree/logs/HEAD diff --git a/tests/iterator/workdir.c b/tests/iterator/workdir.c index 28fcc0d23..165cca5ed 100644 --- a/tests/iterator/workdir.c +++ b/tests/iterator/workdir.c @@ -616,6 +616,7 @@ void test_iterator_workdir__filesystem2(void) "heads/packed-test", "heads/subtrees", "heads/test", + "heads/testrepo-worktree", "tags/e90810b", "tags/foo/bar", "tags/foo/foo/bar", @@ -628,7 +629,7 @@ void test_iterator_workdir__filesystem2(void) cl_git_pass(git_iterator_for_filesystem( &i, "testrepo/.git/refs", NULL)); - expect_iterator_items(i, 13, expect_base, 13, expect_base); + expect_iterator_items(i, 14, expect_base, 14, expect_base); git_iterator_free(i); } diff --git a/tests/refs/list.c b/tests/refs/list.c index 374943b05..b4101ba7a 100644 --- a/tests/refs/list.c +++ b/tests/refs/list.c @@ -36,7 +36,7 @@ void test_refs_list__all(void) /* We have exactly 12 refs in total if we include the packed ones: * there is a reference that exists both in the packfile and as * loose, but we only list it once */ - cl_assert_equal_i((int)ref_list.count, 15); + cl_assert_equal_i((int)ref_list.count, 16); git_strarray_free(&ref_list); } @@ -51,7 +51,7 @@ void test_refs_list__do_not_retrieve_references_which_name_end_with_a_lock_exten "144344043ba4d4a405da03de3844aa829ae8be0e\n"); cl_git_pass(git_reference_list(&ref_list, g_repo)); - cl_assert_equal_i((int)ref_list.count, 15); + cl_assert_equal_i((int)ref_list.count, 16); git_strarray_free(&ref_list); } diff --git a/tests/resources/testrepo-worktree/.gitted b/tests/resources/testrepo-worktree/.gitted new file mode 100644 index 0000000000000000000000000000000000000000..fe4556a92e68ed14b7ac05eb465bcee87ec11fba GIT binary patch literal 53 tcmYe#EJ?{MvQp5~(=SOaE-6Ya$k*3P&n(d|&o9aba#M@p;<_*)E&vVs6XXB@ literal 0 HcmV?d00001 diff --git a/tests/resources/testrepo-worktree/README b/tests/resources/testrepo-worktree/README new file mode 100644 index 0000000000000000000000000000000000000000..a8233120f6ad708f843d861ce2b7228ec4e3dec6 GIT binary patch literal 10 Rcmc~utyCzU`w|QI)3=4p=aCfmE2l$6nVkJOLh~Jb!kqpa?qy&{m=hA@3i7Wc zgNcFxm+Rfu{JXxLJ6aAq?BZi754yRb^;+YPi$SX%OHa&gs*EdjW2#W%@F@iV+^&ba literal 0 HcmV?d00001 diff --git a/tests/resources/testrepo/.gitted/worktrees/testrepo-worktree/logs/HEAD b/tests/resources/testrepo/.gitted/worktrees/testrepo-worktree/logs/HEAD new file mode 100644 index 0000000000000000000000000000000000000000..3bede502ee05ea8314e9e0244b9f43d1f4c6eda8 GIT binary patch literal 214 zcma*g%?$z}5J2IxRxx*@8Tk`7##n-h6(9~SAuI$&ZC^{++dF*8L+7G@_#nL_@1)kw zYGH#oMQaR6h1LZ@F#@iIH_ttV40ooq%)UPv&TU*<9*0yea8ybttCW$jLxH#nGlg8= cJVB|Sw7ekpTGsEl0@L75t?s|I=YP@m2NSJ8JOBUy literal 0 HcmV?d00001 From e5a620de803ddcb0c05e43c6a8d7d6d4baeb808c Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Mon, 9 Nov 2015 17:00:41 +0100 Subject: [PATCH 075/366] tests: add submodule worktree test data Create worktrees for submodule repositories. The worktrees are created for the parent repository (e.g. the one containing submodules) and for the contained child repository. --- tests/resources/submodules-worktree-child/.gitted | Bin 0 -> 72 bytes tests/resources/submodules-worktree-child/README | Bin 0 -> 10 bytes .../submodules-worktree-child/branch_file.txt | Bin 0 -> 8 bytes tests/resources/submodules-worktree-child/new.txt | Bin 0 -> 12 bytes .../submodules-worktree-parent/.gitmodules | Bin 0 -> 98 bytes .../resources/submodules-worktree-parent/.gitted | Bin 0 -> 64 bytes .../resources/submodules-worktree-parent/deleted | Bin 0 -> 3 bytes .../resources/submodules-worktree-parent/modified | Bin 0 -> 3 bytes .../submodules-worktree-parent/unmodified | Bin 0 -> 3 bytes .../logs/refs/heads/submodules-worktree-parent | Bin 0 -> 156 bytes .../.gitted/refs/heads/submodules-worktree-parent | Bin 0 -> 41 bytes .../worktrees/submodules-worktree-parent/HEAD | Bin 0 -> 43 bytes .../submodules-worktree-parent/ORIG_HEAD | Bin 0 -> 41 bytes .../submodules-worktree-parent/commondir | Bin 0 -> 6 bytes .../worktrees/submodules-worktree-parent/gitdir | Bin 0 -> 44 bytes .../worktrees/submodules-worktree-parent/index | Bin 0 -> 441 bytes .../logs/refs/heads/submodules-worktree-child | Bin 0 -> 156 bytes .../.gitted/refs/heads/submodules-worktree-child | Bin 0 -> 41 bytes .../worktrees/submodules-worktree-child/HEAD | Bin 0 -> 42 bytes .../worktrees/submodules-worktree-child/ORIG_HEAD | Bin 0 -> 41 bytes .../worktrees/submodules-worktree-child/commondir | Bin 0 -> 6 bytes .../worktrees/submodules-worktree-child/gitdir | Bin 0 -> 46 bytes .../worktrees/submodules-worktree-child/index | Bin 0 -> 289 bytes 23 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/resources/submodules-worktree-child/.gitted create mode 100644 tests/resources/submodules-worktree-child/README create mode 100644 tests/resources/submodules-worktree-child/branch_file.txt create mode 100644 tests/resources/submodules-worktree-child/new.txt create mode 100644 tests/resources/submodules-worktree-parent/.gitmodules create mode 100644 tests/resources/submodules-worktree-parent/.gitted create mode 100644 tests/resources/submodules-worktree-parent/deleted create mode 100644 tests/resources/submodules-worktree-parent/modified create mode 100644 tests/resources/submodules-worktree-parent/unmodified create mode 100644 tests/resources/submodules/.gitted/logs/refs/heads/submodules-worktree-parent create mode 100644 tests/resources/submodules/.gitted/refs/heads/submodules-worktree-parent create mode 100644 tests/resources/submodules/.gitted/worktrees/submodules-worktree-parent/HEAD create mode 100644 tests/resources/submodules/.gitted/worktrees/submodules-worktree-parent/ORIG_HEAD create mode 100644 tests/resources/submodules/.gitted/worktrees/submodules-worktree-parent/commondir create mode 100644 tests/resources/submodules/.gitted/worktrees/submodules-worktree-parent/gitdir create mode 100644 tests/resources/submodules/.gitted/worktrees/submodules-worktree-parent/index create mode 100644 tests/resources/submodules/testrepo/.gitted/logs/refs/heads/submodules-worktree-child create mode 100644 tests/resources/submodules/testrepo/.gitted/refs/heads/submodules-worktree-child create mode 100644 tests/resources/submodules/testrepo/.gitted/worktrees/submodules-worktree-child/HEAD create mode 100644 tests/resources/submodules/testrepo/.gitted/worktrees/submodules-worktree-child/ORIG_HEAD create mode 100644 tests/resources/submodules/testrepo/.gitted/worktrees/submodules-worktree-child/commondir create mode 100644 tests/resources/submodules/testrepo/.gitted/worktrees/submodules-worktree-child/gitdir create mode 100644 tests/resources/submodules/testrepo/.gitted/worktrees/submodules-worktree-child/index diff --git a/tests/resources/submodules-worktree-child/.gitted b/tests/resources/submodules-worktree-child/.gitted new file mode 100644 index 0000000000000000000000000000000000000000..03286f522907adee181866b2b81be0fcc4ab6979 GIT binary patch literal 72 zcmYe#EJ?{MvQp5~(=RSf%FRzH%}FiRFG(#fDM~HK*VjwWEYUB|FUkgTf#L`yx-dcA KD+zEXh!?Re%X`ah4Y40Qvf%#i>Qb`bA0l k#YM^bIhjf6nI%U0AXPxY)Z+ZoqU6+KFdt-)9#EDG0J8cc9RL6T literal 0 HcmV?d00001 diff --git a/tests/resources/submodules-worktree-parent/.gitted b/tests/resources/submodules-worktree-parent/.gitted new file mode 100644 index 0000000000000000000000000000000000000000..87bd9ae29417dc439261769d615e7c45db0ddf0e GIT binary patch literal 64 zcmYe#EJ?{MvQp5~(=RSf%FRzH%}FiR*GtbV(J#+0$}TBN1#%HGx-dcAg2bZKyb>+| D1@{;= literal 0 HcmV?d00001 diff --git a/tests/resources/submodules-worktree-parent/deleted b/tests/resources/submodules-worktree-parent/deleted new file mode 100644 index 0000000000000000000000000000000000000000..092bfb9bdf74dd8cfd22e812151281ee9aa6f01a GIT binary patch literal 3 Kcmb=-=K=r%Rsiz= literal 0 HcmV?d00001 diff --git a/tests/resources/submodules-worktree-parent/modified b/tests/resources/submodules-worktree-parent/modified new file mode 100644 index 0000000000000000000000000000000000000000..092bfb9bdf74dd8cfd22e812151281ee9aa6f01a GIT binary patch literal 3 Kcmb=-=K=r%Rsiz= literal 0 HcmV?d00001 diff --git a/tests/resources/submodules-worktree-parent/unmodified b/tests/resources/submodules-worktree-parent/unmodified new file mode 100644 index 0000000000000000000000000000000000000000..092bfb9bdf74dd8cfd22e812151281ee9aa6f01a GIT binary patch literal 3 Kcmb=-=K=r%Rsiz= literal 0 HcmV?d00001 diff --git a/tests/resources/submodules/.gitted/logs/refs/heads/submodules-worktree-parent b/tests/resources/submodules/.gitted/logs/refs/heads/submodules-worktree-parent new file mode 100644 index 0000000000000000000000000000000000000000..65e98853528b8ebec8b75c1e91a28d34eaa32150 GIT binary patch literal 156 zcma*UK?=e!5Czb+o?`Zb{KRQGDI$srE(K38NmCk1Ye{o|yn^om{~_OscVZAu*1$5W zvnrMw36dbjr#M6>4d|`4b1paTrB3q_YWc62XE PYwBqz-Ik6;p);Z&&&6_}+X2|Fx~P-FVF^T_(jQ3>Y& literal 0 HcmV?d00001 diff --git a/tests/resources/submodules/.gitted/worktrees/submodules-worktree-parent/HEAD b/tests/resources/submodules/.gitted/worktrees/submodules-worktree-parent/HEAD new file mode 100644 index 0000000000000000000000000000000000000000..a07134b85d6c4da0beff679a9ad6fa1680941235 GIT binary patch literal 43 ycmXR)O|w!cN=+-)&qz&7Db_D8P0GzrDa}bO)-BI3$}TBNP1P+(EK1EQ;Q|0;=nzi; literal 0 HcmV?d00001 diff --git a/tests/resources/submodules/.gitted/worktrees/submodules-worktree-parent/ORIG_HEAD b/tests/resources/submodules/.gitted/worktrees/submodules-worktree-parent/ORIG_HEAD new file mode 100644 index 0000000000000000000000000000000000000000..32b935853701f9b5a0ff56cde617a37403860cc8 GIT binary patch literal 41 ucmV~$!4Uu;2m`Rc(?CTm;{b>Ik6;p);Z&&&6_}+X2|Fx~P-FVF^T_(jQ3>Y& literal 0 HcmV?d00001 diff --git a/tests/resources/submodules/.gitted/worktrees/submodules-worktree-parent/commondir b/tests/resources/submodules/.gitted/worktrees/submodules-worktree-parent/commondir new file mode 100644 index 0000000000000000000000000000000000000000..aab0408ceca61b98818f783c76b074312fd5cd80 GIT binary patch literal 6 NcmdPX)7R7E0ssT70P+9; literal 0 HcmV?d00001 diff --git a/tests/resources/submodules/.gitted/worktrees/submodules-worktree-parent/gitdir b/tests/resources/submodules/.gitted/worktrees/submodules-worktree-parent/gitdir new file mode 100644 index 0000000000000000000000000000000000000000..eaaf13b9560a93c6923755353b00b9ca611834d3 GIT binary patch literal 44 scmdPX)7OKc;?ktt{FKt1)MDN8{G#lVqSRE~g2bZKyb^uA^vn`204c~0asU7T literal 0 HcmV?d00001 diff --git a/tests/resources/submodules/.gitted/worktrees/submodules-worktree-parent/index b/tests/resources/submodules/.gitted/worktrees/submodules-worktree-parent/index new file mode 100644 index 0000000000000000000000000000000000000000..5b68f18a4c0d3a4d650a5186d49be9a1ecffaec7 GIT binary patch literal 441 zcmZ?q402{*U|<4b)-Z-N@-4NG0-p&fSCiMq2{rnna9kj{d@NPlDj>Bm0k#m z3N^l)wd{iw1A9tpPHIVN3T|`Qi86-+=%&oHOprk^cfe?{dv-DJVPJRwv<2or0fuGq zZ$Hm^|AguC?mU(IzW(t~LdpXeI7(8BONvqp@^P56gOh_O_i&ZwAzTEs76?LuTwQ^b zB!j7f0oOMEn{Ao1m%Mz|{fhm3U!}c~-H#6a_kY*%7oYb#5Wb9mVnJ7ux!ndg02ouA A1ONa4 literal 0 HcmV?d00001 diff --git a/tests/resources/submodules/testrepo/.gitted/logs/refs/heads/submodules-worktree-child b/tests/resources/submodules/testrepo/.gitted/logs/refs/heads/submodules-worktree-child new file mode 100644 index 0000000000000000000000000000000000000000..dd4650ff8b2465e234a5311d83ef4484fab5974b GIT binary patch literal 156 zcma*cOA5j;5CG7%o?`ZbOw&oDMWmvFOTiONIx{qsen@kF^a#G~L;MeL<4witGpi|~ zlRCym9f^^U{f<0^;1S+ja_UF;6ixHMSqfa%ty{V%$!ucl8O@C<{d;ck7v1P+rj%UmdoVq&k>sM;1lNb-*7JjdtPce z)SQqYSCIQ88H^PSxTg5<=lT9}jEu|MeD2L{k+1v@8 Date: Tue, 10 Nov 2015 15:53:09 +0100 Subject: [PATCH 076/366] tests: add merge-conflict branch for testrepo Add a new branch that causes a merge conflict to `testrepo` so that we are able to test merging in worktrees. --- tests/iterator/workdir.c | 3 ++- tests/refs/list.c | 4 ++-- .../9b/1719f5cf069568785080a0bbabbe7c377e22ae | Bin 0 -> 24 bytes .../a3/8d028f71eaa590febb7d716b1ca32350cf70da | Bin 0 -> 155 bytes .../ad/edac69457183c8265c8a9614c1c4fed31d1ff3 | Bin 0 -> 119 bytes .../testrepo/.gitted/refs/heads/merge-conflict | Bin 0 -> 41 bytes tests/revwalk/basic.c | 2 +- 7 files changed, 5 insertions(+), 4 deletions(-) create mode 100644 tests/resources/testrepo/.gitted/objects/9b/1719f5cf069568785080a0bbabbe7c377e22ae create mode 100644 tests/resources/testrepo/.gitted/objects/a3/8d028f71eaa590febb7d716b1ca32350cf70da create mode 100644 tests/resources/testrepo/.gitted/objects/ad/edac69457183c8265c8a9614c1c4fed31d1ff3 create mode 100644 tests/resources/testrepo/.gitted/refs/heads/merge-conflict diff --git a/tests/iterator/workdir.c b/tests/iterator/workdir.c index 165cca5ed..f33fd98f1 100644 --- a/tests/iterator/workdir.c +++ b/tests/iterator/workdir.c @@ -613,6 +613,7 @@ void test_iterator_workdir__filesystem2(void) "heads/ident", "heads/long-file-name", "heads/master", + "heads/merge-conflict", "heads/packed-test", "heads/subtrees", "heads/test", @@ -629,7 +630,7 @@ void test_iterator_workdir__filesystem2(void) cl_git_pass(git_iterator_for_filesystem( &i, "testrepo/.git/refs", NULL)); - expect_iterator_items(i, 14, expect_base, 14, expect_base); + expect_iterator_items(i, 15, expect_base, 15, expect_base); git_iterator_free(i); } diff --git a/tests/refs/list.c b/tests/refs/list.c index b4101ba7a..f7ca3f707 100644 --- a/tests/refs/list.c +++ b/tests/refs/list.c @@ -36,7 +36,7 @@ void test_refs_list__all(void) /* We have exactly 12 refs in total if we include the packed ones: * there is a reference that exists both in the packfile and as * loose, but we only list it once */ - cl_assert_equal_i((int)ref_list.count, 16); + cl_assert_equal_i((int)ref_list.count, 17); git_strarray_free(&ref_list); } @@ -51,7 +51,7 @@ void test_refs_list__do_not_retrieve_references_which_name_end_with_a_lock_exten "144344043ba4d4a405da03de3844aa829ae8be0e\n"); cl_git_pass(git_reference_list(&ref_list, g_repo)); - cl_assert_equal_i((int)ref_list.count, 16); + cl_assert_equal_i((int)ref_list.count, 17); git_strarray_free(&ref_list); } diff --git a/tests/resources/testrepo/.gitted/objects/9b/1719f5cf069568785080a0bbabbe7c377e22ae b/tests/resources/testrepo/.gitted/objects/9b/1719f5cf069568785080a0bbabbe7c377e22ae new file mode 100644 index 0000000000000000000000000000000000000000..13e3f581a83ab9bb85f981c1ced8c88be9a191f4 GIT binary patch literal 24 gcmbW%hJpR z$UEz*j*AwSG*QejqKqL$8F@-T0zy>_LV;Rw*tqLzZdQy5S+V9R&S55uIEyH944I2( zs<|ejf!}s}c6VXxP44b$+SVKQV(z%T&fEQUXv@g~QHGQzAKc!9_k;X?rvJ+?UF)NX J4IlRaMI(p8ODF&U literal 0 HcmV?d00001 diff --git a/tests/resources/testrepo/.gitted/objects/ad/edac69457183c8265c8a9614c1c4fed31d1ff3 b/tests/resources/testrepo/.gitted/objects/ad/edac69457183c8265c8a9614c1c4fed31d1ff3 new file mode 100644 index 0000000000000000000000000000000000000000..c054fc0c4845646a59fa291938a981d056e7e3f3 GIT binary patch literal 119 zcmV--0Eqv10V^p=O;s>7G-5C`FfcPQQ3!H%bn$g%SfOmF@NI2De~WFK%%kl}eMcVO zI|fyeRFs&PoDrXvnUktlQc=P%TU_$%dA6w;6#)$kcCX%7V_v7U4yrUSwH&NuxoF$L Z`!ANuE literal 0 HcmV?d00001 diff --git a/tests/resources/testrepo/.gitted/refs/heads/merge-conflict b/tests/resources/testrepo/.gitted/refs/heads/merge-conflict new file mode 100644 index 0000000000000000000000000000000000000000..3e24a24e06317336f3d0cff372a6ffa1443bfd3e GIT binary patch literal 41 vcmV~$Nf7`r2n4Wy)o=`j%2_V|5}H7xNn)J`utz(Y-p)6 16 */ - cl_assert_equal_i(18, i); + cl_assert_equal_i(19, i); } void test_revwalk_basic__push_head(void) From 807d57e7df1b7f71abc445523b88262b63b1b4e3 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 11 Nov 2015 10:54:41 +0100 Subject: [PATCH 077/366] tests: implement worktree helpers --- tests/worktree/worktree_helpers.c | 30 ++++++++++++++++++++++++++++++ tests/worktree/worktree_helpers.h | 11 +++++++++++ 2 files changed, 41 insertions(+) create mode 100644 tests/worktree/worktree_helpers.c create mode 100644 tests/worktree/worktree_helpers.h diff --git a/tests/worktree/worktree_helpers.c b/tests/worktree/worktree_helpers.c new file mode 100644 index 000000000..6d4cdbaeb --- /dev/null +++ b/tests/worktree/worktree_helpers.c @@ -0,0 +1,30 @@ +#include "clar_libgit2.h" +#include "worktree_helpers.h" + +void cleanup_fixture_worktree(worktree_fixture *fixture) +{ + if (!fixture) + return; + + if (fixture->repo) { + git_repository_free(fixture->repo); + fixture->repo = NULL; + } + if (fixture->worktree) { + git_repository_free(fixture->worktree); + fixture->worktree = NULL; + } + + if (fixture->reponame) + cl_fixture_cleanup(fixture->reponame); + if (fixture->worktreename) + cl_fixture_cleanup(fixture->worktreename); +} + +void setup_fixture_worktree(worktree_fixture *fixture) +{ + if (fixture->reponame) + fixture->repo = cl_git_sandbox_init(fixture->reponame); + if (fixture->worktreename) + fixture->worktree = cl_git_sandbox_init(fixture->worktreename); +} diff --git a/tests/worktree/worktree_helpers.h b/tests/worktree/worktree_helpers.h new file mode 100644 index 000000000..35ea9ed4c --- /dev/null +++ b/tests/worktree/worktree_helpers.h @@ -0,0 +1,11 @@ +typedef struct { + const char *reponame; + const char *worktreename; + git_repository *repo; + git_repository *worktree; +} worktree_fixture; + +#define WORKTREE_FIXTURE_INIT(repo, worktree) { (repo), (worktree), NULL, NULL } + +void cleanup_fixture_worktree(worktree_fixture *fixture); +void setup_fixture_worktree(worktree_fixture *fixture); From c09fd54e2ecb5d43c281ee0fccef6d95787ec510 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 16 Sep 2015 12:10:11 +0200 Subject: [PATCH 078/366] repository: introduce commondir variable The commondir variable stores the path to the common directory. The common directory is used to store objects and references shared across multiple repositories. A current use case is the newly introduced `git worktree` feature, which sets up a separate working copy, where the backing git object store and references are pointed to by the common directory. --- include/git2/repository.h | 11 ++++++ src/repository.c | 81 +++++++++++++++++++++++++++++++-------- src/repository.h | 1 + tests/worktree/open.c | 60 +++++++++++++++++++++++++++++ 4 files changed, 138 insertions(+), 15 deletions(-) create mode 100644 tests/worktree/open.c diff --git a/include/git2/repository.h b/include/git2/repository.h index 3d70d1b89..f60544553 100644 --- a/include/git2/repository.h +++ b/include/git2/repository.h @@ -392,6 +392,17 @@ GIT_EXTERN(const char *) git_repository_path(git_repository *repo); */ GIT_EXTERN(const char *) git_repository_workdir(git_repository *repo); +/** + * Get the path of the shared common directory for this repository + * + * If the repository is bare is not a worktree, the git directory + * path is returned. + * + * @param repo A repository object + * @return the path to the common dir + */ +GIT_EXTERN(const char *) git_repository_commondir(git_repository *repo); + /** * Set the path to the working directory for this repository * diff --git a/src/repository.c b/src/repository.c index 2185632bf..71b6ec44f 100644 --- a/src/repository.c +++ b/src/repository.c @@ -38,6 +38,8 @@ GIT__USE_STRMAP static int check_repositoryformatversion(git_config *config); +#define GIT_COMMONDIR_FILE "commondir" + #define GIT_FILE_CONTENT_PREFIX "gitdir:" #define GIT_BRANCH_MASTER "master" @@ -143,6 +145,7 @@ void git_repository_free(git_repository *repo) git__free(repo->path_gitlink); git__free(repo->path_repository); + git__free(repo->commondir); git__free(repo->workdir); git__free(repo->namespace); git__free(repo->ident_name); @@ -157,17 +160,41 @@ void git_repository_free(git_repository *repo) * * Open a repository object from its path */ -static bool valid_repository_path(git_buf *repository_path) +static bool valid_repository_path(git_buf *repository_path, git_buf *common_path) { - /* Check OBJECTS_DIR first, since it will generate the longest path name */ - if (git_path_contains_dir(repository_path, GIT_OBJECTS_DIR) == false) - return false; + /* Check if we have a separate commondir (e.g. we have a + * worktree) */ + if (git_path_contains_file(repository_path, GIT_COMMONDIR_FILE)) { + git_buf common_link = GIT_BUF_INIT; + git_buf_joinpath(&common_link, repository_path->ptr, GIT_COMMONDIR_FILE); + + git_futils_readbuffer(&common_link, common_link.ptr); + git_buf_rtrim(&common_link); + + if (git_path_is_relative(common_link.ptr)) { + git_buf_joinpath(common_path, repository_path->ptr, common_link.ptr); + } else { + git_buf_swap(common_path, &common_link); + } + + git_buf_free(&common_link); + } + else { + git_buf_set(common_path, repository_path->ptr, repository_path->size); + } + + /* Make sure the commondir path always has a trailing * slash */ + if (git_buf_rfind(common_path, '/') != (ssize_t)common_path->size - 1) + git_buf_putc(common_path, '/'); /* Ensure HEAD file exists */ if (git_path_contains_file(repository_path, GIT_HEAD_FILE) == false) return false; - if (git_path_contains_dir(repository_path, GIT_REFS_DIR) == false) + /* Check files in common dir */ + if (git_path_contains_dir(common_path, GIT_OBJECTS_DIR) == false) + return false; + if (git_path_contains_dir(common_path, GIT_REFS_DIR) == false) return false; return true; @@ -356,6 +383,7 @@ static int find_repo( git_buf *repo_path, git_buf *parent_path, git_buf *link_path, + git_buf *common_path, const char *start_path, uint32_t flags, const char *ceiling_dirs) @@ -363,6 +391,7 @@ static int find_repo( int error; git_buf path = GIT_BUF_INIT; git_buf repo_link = GIT_BUF_INIT; + git_buf common_link = GIT_BUF_INIT; struct stat st; dev_t initial_device = 0; int min_iterations; @@ -409,9 +438,13 @@ static int find_repo( break; if (S_ISDIR(st.st_mode)) { - if (valid_repository_path(&path)) { + if (valid_repository_path(&path, &common_link)) { git_path_to_dir(&path); git_buf_set(repo_path, path.ptr, path.size); + + if (common_path) + git_buf_swap(&common_link, common_path); + break; } } @@ -419,11 +452,13 @@ static int find_repo( error = read_gitfile(&repo_link, path.ptr); if (error < 0) break; - if (valid_repository_path(&repo_link)) { + if (valid_repository_path(&repo_link, &common_link)) { git_buf_swap(repo_path, &repo_link); if (link_path) error = git_buf_put(link_path, path.ptr, path.size); + if (common_path) + git_buf_swap(&common_link, common_path); } break; } @@ -470,6 +505,7 @@ static int find_repo( git_buf_free(&path); git_buf_free(&repo_link); + git_buf_free(&common_link); return error; } @@ -478,14 +514,15 @@ int git_repository_open_bare( const char *bare_path) { int error; - git_buf path = GIT_BUF_INIT; + git_buf path = GIT_BUF_INIT, common_path = GIT_BUF_INIT; git_repository *repo = NULL; if ((error = git_path_prettify_dir(&path, bare_path, NULL)) < 0) return error; - if (!valid_repository_path(&path)) { + if (!valid_repository_path(&path, &common_path)) { git_buf_free(&path); + git_buf_free(&common_path); giterr_set(GITERR_REPOSITORY, "path is not a repository: %s", bare_path); return GIT_ENOTFOUND; } @@ -495,6 +532,8 @@ int git_repository_open_bare( repo->path_repository = git_buf_detach(&path); GITERR_CHECK_ALLOC(repo->path_repository); + repo->commondir = git_buf_detach(&common_path); + GITERR_CHECK_ALLOC(repo->commondir); /* of course we're bare! */ repo->is_bare = 1; @@ -681,7 +720,7 @@ int git_repository_open_ext( { int error; git_buf path = GIT_BUF_INIT, parent = GIT_BUF_INIT, - link_path = GIT_BUF_INIT; + link_path = GIT_BUF_INIT, common_path = GIT_BUF_INIT; git_repository *repo; git_config *config = NULL; @@ -692,7 +731,7 @@ int git_repository_open_ext( *repo_ptr = NULL; error = find_repo( - &path, &parent, &link_path, start_path, flags, ceiling_dirs); + &path, &parent, &link_path, &common_path, start_path, flags, ceiling_dirs); if (error < 0 || !repo_ptr) return error; @@ -707,6 +746,10 @@ int git_repository_open_ext( repo->path_gitlink = git_buf_detach(&link_path); GITERR_CHECK_ALLOC(repo->path_gitlink); } + if (common_path.size) { + repo->commondir = git_buf_detach(&common_path); + GITERR_CHECK_ALLOC(repo->commondir); + } /* * We'd like to have the config, but git doesn't particularly @@ -773,7 +816,7 @@ int git_repository_discover( git_buf_sanitize(out); - return find_repo(out, NULL, NULL, start_path, flags, ceiling_dirs); + return find_repo(out, NULL, NULL, NULL, start_path, flags, ceiling_dirs); } static int load_config( @@ -928,7 +971,7 @@ int git_repository_odb__weakptr(git_odb **out, git_repository *repo) git_buf odb_path = GIT_BUF_INIT; git_odb *odb; - if ((error = git_buf_joinpath(&odb_path, repo->path_repository, GIT_OBJECTS_DIR)) < 0) + if ((error = git_buf_joinpath(&odb_path, repo->commondir, GIT_OBJECTS_DIR)) < 0) return error; error = git_odb_open(&odb, odb_path.ptr); @@ -1856,7 +1899,8 @@ int git_repository_init_ext( git_repository_init_options *opts) { int error; - git_buf repo_path = GIT_BUF_INIT, wd_path = GIT_BUF_INIT; + git_buf repo_path = GIT_BUF_INIT, wd_path = GIT_BUF_INIT, + common_path = GIT_BUF_INIT; const char *wd; assert(out && given_repo && opts); @@ -1868,7 +1912,7 @@ int git_repository_init_ext( goto cleanup; wd = (opts->flags & GIT_REPOSITORY_INIT_BARE) ? NULL : git_buf_cstr(&wd_path); - if (valid_repository_path(&repo_path)) { + if (valid_repository_path(&repo_path, &common_path)) { if ((opts->flags & GIT_REPOSITORY_INIT_NO_REINIT) != 0) { giterr_set(GITERR_REPOSITORY, @@ -1901,6 +1945,7 @@ int git_repository_init_ext( error = repo_init_create_origin(*out, opts->origin_url); cleanup: + git_buf_free(&common_path); git_buf_free(&repo_path); git_buf_free(&wd_path); @@ -2023,6 +2068,12 @@ const char *git_repository_workdir(git_repository *repo) return repo->workdir; } +const char *git_repository_commondir(git_repository *repo) +{ + assert(repo); + return repo->commondir; +} + int git_repository_set_workdir( git_repository *repo, const char *workdir, int update_gitlink) { diff --git a/src/repository.h b/src/repository.h index 9d276f376..5dc67218f 100644 --- a/src/repository.h +++ b/src/repository.h @@ -128,6 +128,7 @@ struct git_repository { char *path_repository; char *path_gitlink; + char *commondir; char *workdir; char *namespace; diff --git a/tests/worktree/open.c b/tests/worktree/open.c new file mode 100644 index 000000000..772f7601f --- /dev/null +++ b/tests/worktree/open.c @@ -0,0 +1,60 @@ +#include "clar_libgit2.h" +#include "worktree_helpers.h" + +#define WORKTREE_PARENT "submodules-worktree-parent" +#define WORKTREE_CHILD "submodules-worktree-child" + +void test_worktree_open__repository(void) +{ + worktree_fixture fixture = + WORKTREE_FIXTURE_INIT("testrepo", "testrepo-worktree"); + setup_fixture_worktree(&fixture); + + cl_assert(git_repository_path(fixture.worktree) != NULL); + cl_assert(git_repository_workdir(fixture.worktree) != NULL); + + cleanup_fixture_worktree(&fixture); +} + +void test_worktree_open__repository_with_nonexistent_parent(void) +{ + git_repository *repo; + + cl_fixture_sandbox("testrepo-worktree"); + cl_git_pass(p_chdir("testrepo-worktree")); + cl_git_pass(cl_rename(".gitted", ".git")); + cl_git_pass(p_chdir("..")); + + cl_git_fail(git_repository_open(&repo, "testrepo-worktree")); + + cl_fixture_cleanup("testrepo-worktree"); +} + +void test_worktree_open__submodule_worktree_parent(void) +{ + worktree_fixture fixture = + WORKTREE_FIXTURE_INIT("submodules", WORKTREE_PARENT); + setup_fixture_worktree(&fixture); + + cl_assert(git_repository_path(fixture.worktree) != NULL); + cl_assert(git_repository_workdir(fixture.worktree) != NULL); + + cleanup_fixture_worktree(&fixture); +} + +void test_worktree_open__submodule_worktree_child(void) +{ + worktree_fixture parent_fixture = + WORKTREE_FIXTURE_INIT("submodules", WORKTREE_PARENT); + worktree_fixture child_fixture = + WORKTREE_FIXTURE_INIT(NULL, WORKTREE_CHILD); + + setup_fixture_worktree(&parent_fixture); + cl_git_pass(p_rename( + "submodules/testrepo/.gitted", + "submodules/testrepo/.git")); + setup_fixture_worktree(&child_fixture); + + cleanup_fixture_worktree(&child_fixture); + cleanup_fixture_worktree(&parent_fixture); +} From cb3269c970db6766f8a953fee438b56119fd9847 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 11 Nov 2016 13:46:59 +0100 Subject: [PATCH 079/366] repository: add function to retrieve paths for repo items --- include/git2/repository.h | 36 +++++++++++++++++++++++ src/repository.c | 61 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) diff --git a/include/git2/repository.h b/include/git2/repository.h index f60544553..74ce4c795 100644 --- a/include/git2/repository.h +++ b/include/git2/repository.h @@ -370,6 +370,42 @@ GIT_EXTERN(int) git_repository_head_unborn(git_repository *repo); */ GIT_EXTERN(int) git_repository_is_empty(git_repository *repo); +/** + * List of items which belong to the git repository layout + */ +typedef enum { + GIT_REPOSITORY_ITEM_GITDIR, + GIT_REPOSITORY_ITEM_WORKDIR, + GIT_REPOSITORY_ITEM_COMMONDIR, + GIT_REPOSITORY_ITEM_INDEX, + GIT_REPOSITORY_ITEM_OBJECTS, + GIT_REPOSITORY_ITEM_REFS, + GIT_REPOSITORY_ITEM_PACKED_REFS, + GIT_REPOSITORY_ITEM_REMOTES, + GIT_REPOSITORY_ITEM_CONFIG, + GIT_REPOSITORY_ITEM_INFO, + GIT_REPOSITORY_ITEM_HOOKS, + GIT_REPOSITORY_ITEM_LOGS, + GIT_REPOSITORY_ITEM_MODULES, + GIT_REPOSITORY_ITEM_WORKTREES +} git_repository_item_t; + +/** + * Get the location of a specific repository file or directory + * + * This function will retrieve the path of a specific repository + * item. It will thereby honor things like the repository's + * common directory, gitdir, etc. In case a file path cannot + * exist for a given item (e.g. the working directory of a bare + * repository), an error is returned. + * + * @param out Buffer to store the path at + * @param repo Repository to get path for + * @param item The repository item for which to retrieve the path + * @return 0 on success, otherwise a negative value + */ +GIT_EXTERN(int) git_repository_item_path(git_buf *out, git_repository *repo, git_repository_item_t item); + /** * Get the path of this repository * diff --git a/src/repository.c b/src/repository.c index 71b6ec44f..14ad7a599 100644 --- a/src/repository.c +++ b/src/repository.c @@ -36,6 +36,27 @@ GIT__USE_STRMAP # include "win32/w32_util.h" #endif +static const struct { + git_repository_item_t parent; + const char *name; + bool directory; +} items[] = { + { GIT_REPOSITORY_ITEM_GITDIR, NULL, true }, + { GIT_REPOSITORY_ITEM_WORKDIR, NULL, true }, + { GIT_REPOSITORY_ITEM_COMMONDIR, NULL, true }, + { GIT_REPOSITORY_ITEM_GITDIR, "index", false }, + { GIT_REPOSITORY_ITEM_COMMONDIR, "objects", true }, + { GIT_REPOSITORY_ITEM_COMMONDIR, "refs", true }, + { GIT_REPOSITORY_ITEM_COMMONDIR, "packed-refs", false }, + { GIT_REPOSITORY_ITEM_COMMONDIR, "remotes", true }, + { GIT_REPOSITORY_ITEM_COMMONDIR, "config", false }, + { GIT_REPOSITORY_ITEM_COMMONDIR, "info", true }, + { GIT_REPOSITORY_ITEM_COMMONDIR, "hooks", true }, + { GIT_REPOSITORY_ITEM_COMMONDIR, "logs", true }, + { GIT_REPOSITORY_ITEM_GITDIR, "modules", true }, + { GIT_REPOSITORY_ITEM_COMMONDIR, "worktrees", true } +}; + static int check_repositoryformatversion(git_config *config); #define GIT_COMMONDIR_FILE "commondir" @@ -2052,6 +2073,46 @@ int git_repository_is_empty(git_repository *repo) return is_empty; } +int git_repository_item_path(git_buf *out, git_repository *repo, git_repository_item_t item) +{ + const char *parent; + + switch (items[item].parent) { + case GIT_REPOSITORY_ITEM_GITDIR: + parent = git_repository_path(repo); + break; + case GIT_REPOSITORY_ITEM_WORKDIR: + parent = git_repository_workdir(repo); + break; + case GIT_REPOSITORY_ITEM_COMMONDIR: + parent = git_repository_commondir(repo); + break; + default: + giterr_set(GITERR_INVALID, "Invalid item directory"); + return -1; + } + + if (parent == NULL) { + giterr_set(GITERR_INVALID, "Path cannot exist in repository"); + return -1; + } + + if (git_buf_sets(out, parent) < 0) + return -1; + + if (items[item].name) { + if (git_buf_joinpath(out, parent, items[item].name) < 0) + return -1; + } + + if (items[item].directory) { + if (git_path_to_dir(out) < 0) + return -1; + } + + return 0; +} + const char *git_repository_path(git_repository *repo) { assert(repo); From c5f3da9692f8de15550fed47e377c586f99f7c5a Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 11 Nov 2016 14:36:43 +0100 Subject: [PATCH 080/366] repository: use `git_repository_item_path` The recent introduction of the commondir variable of a repository requires callers to distinguish whether their files are part of the dot-git directory or the common directory shared between multpile worktrees. In order to take the burden from callers and unify knowledge on which files reside where, the `git_repository_item_path` function has been introduced which encapsulate this knowledge. Modify most existing callers of `git_repository_path` to use `git_repository_item_path` instead, thus making them implicitly aware of the common directory. --- src/attr.c | 36 +++++++++++++++++++++++------------- src/attr_file.h | 2 +- src/blob.c | 4 ++-- src/clone.c | 5 ++--- src/ignore.c | 8 +++++++- src/ignore.h | 2 +- src/repository.c | 3 ++- src/submodule.c | 12 ++++++++---- src/transports/local.c | 3 ++- 9 files changed, 48 insertions(+), 27 deletions(-) diff --git a/src/attr.c b/src/attr.c index d43a15f50..93dea123f 100644 --- a/src/attr.c +++ b/src/attr.c @@ -292,7 +292,7 @@ static int attr_setup(git_repository *repo, git_attr_session *attr_session) int error = 0; const char *workdir = git_repository_workdir(repo); git_index *idx = NULL; - git_buf sys = GIT_BUF_INIT; + git_buf path = GIT_BUF_INIT; if (attr_session && attr_session->init_setup) return 0; @@ -304,40 +304,45 @@ static int attr_setup(git_repository *repo, git_attr_session *attr_session) * definitions will be available for later file parsing */ - error = system_attr_file(&sys, attr_session); + error = system_attr_file(&path, attr_session); if (error == 0) error = preload_attr_file( - repo, attr_session, GIT_ATTR_FILE__FROM_FILE, NULL, sys.ptr); + repo, attr_session, GIT_ATTR_FILE__FROM_FILE, NULL, path.ptr); if (error != GIT_ENOTFOUND) - return error; - - git_buf_free(&sys); + goto out; if ((error = preload_attr_file( repo, attr_session, GIT_ATTR_FILE__FROM_FILE, NULL, git_repository_attr_cache(repo)->cfg_attr_file)) < 0) - return error; + goto out; + + if ((error = git_repository_item_path(&path, + repo, GIT_REPOSITORY_ITEM_INFO)) < 0) + goto out; if ((error = preload_attr_file( repo, attr_session, GIT_ATTR_FILE__FROM_FILE, - git_repository_path(repo), GIT_ATTR_FILE_INREPO)) < 0) - return error; + path.ptr, GIT_ATTR_FILE_INREPO)) < 0) + goto out; if (workdir != NULL && (error = preload_attr_file( repo, attr_session, GIT_ATTR_FILE__FROM_FILE, workdir, GIT_ATTR_FILE)) < 0) - return error; + goto out; if ((error = git_repository_index__weakptr(&idx, repo)) < 0 || (error = preload_attr_file( repo, attr_session, GIT_ATTR_FILE__FROM_INDEX, NULL, GIT_ATTR_FILE)) < 0) - return error; + goto out; if (attr_session) attr_session->init_setup = 1; +out: + git_buf_free(&path); + return error; } @@ -472,7 +477,7 @@ static int collect_attr_files( git_vector *files) { int error = 0; - git_buf dir = GIT_BUF_INIT; + git_buf dir = GIT_BUF_INIT, attrfile = GIT_BUF_INIT; const char *workdir = git_repository_workdir(repo); attr_walk_up_info info = { NULL }; @@ -494,9 +499,13 @@ static int collect_attr_files( * - $GIT_PREFIX/etc/gitattributes */ + error = git_repository_item_path(&attrfile, repo, GIT_REPOSITORY_ITEM_INFO); + if (error < 0) + goto cleanup; + error = push_attr_file( repo, attr_session, files, GIT_ATTR_FILE__FROM_FILE, - git_repository_path(repo), GIT_ATTR_FILE_INREPO); + attrfile.ptr, GIT_ATTR_FILE_INREPO); if (error < 0) goto cleanup; @@ -538,6 +547,7 @@ static int collect_attr_files( cleanup: if (error < 0) release_attr_files(files); + git_buf_free(&attrfile); git_buf_free(&dir); return error; diff --git a/src/attr_file.h b/src/attr_file.h index 388ecf4c0..a9af2403a 100644 --- a/src/attr_file.h +++ b/src/attr_file.h @@ -15,7 +15,7 @@ #include "fileops.h" #define GIT_ATTR_FILE ".gitattributes" -#define GIT_ATTR_FILE_INREPO "info/attributes" +#define GIT_ATTR_FILE_INREPO "attributes" #define GIT_ATTR_FILE_SYSTEM "gitattributes" #define GIT_ATTR_FILE_XDG "attributes" diff --git a/src/blob.c b/src/blob.c index cd5df3537..19d3039fb 100644 --- a/src/blob.c +++ b/src/blob.c @@ -326,8 +326,8 @@ int git_blob_create_fromstream(git_writestream **out, git_repository *repo, cons stream->parent.close = blob_writestream_close; stream->parent.free = blob_writestream_free; - if ((error = git_buf_joinpath(&path, - git_repository_path(repo), GIT_OBJECTS_DIR "streamed")) < 0) + if ((error = git_repository_item_path(&path, repo, GIT_REPOSITORY_ITEM_OBJECTS)) < 0 + || (error = git_buf_joinpath(&path, path.ptr, "streamed")) < 0) goto cleanup; if ((error = git_filebuf_open_withsize(&stream->fbuf, git_buf_cstr(&path), GIT_FILEBUF_TEMPORARY, diff --git a/src/clone.c b/src/clone.c index 0d4756e28..16ddface2 100644 --- a/src/clone.c +++ b/src/clone.c @@ -513,9 +513,8 @@ static int clone_local_into(git_repository *repo, git_remote *remote, const git_ return error; } - git_buf_joinpath(&src_odb, git_repository_path(src), GIT_OBJECTS_DIR); - git_buf_joinpath(&dst_odb, git_repository_path(repo), GIT_OBJECTS_DIR); - if (git_buf_oom(&src_odb) || git_buf_oom(&dst_odb)) { + if (git_repository_item_path(&src_odb, src, GIT_REPOSITORY_ITEM_OBJECTS) < 0 + || git_repository_item_path(&dst_odb, repo, GIT_REPOSITORY_ITEM_OBJECTS) < 0) { error = -1; goto cleanup; } diff --git a/src/ignore.c b/src/ignore.c index cc9e08e35..c324d4dd4 100644 --- a/src/ignore.c +++ b/src/ignore.c @@ -277,6 +277,7 @@ int git_ignore__for_path( { int error = 0; const char *workdir = git_repository_workdir(repo); + git_buf infopath = GIT_BUF_INIT; assert(repo && ignores && path); @@ -322,10 +323,14 @@ int git_ignore__for_path( goto cleanup; } + if ((error = git_repository_item_path(&infopath, + repo, GIT_REPOSITORY_ITEM_INFO)) < 0) + goto cleanup; + /* load .git/info/exclude */ error = push_ignore_file( ignores, &ignores->ign_global, - git_repository_path(repo), GIT_IGNORE_FILE_INREPO); + infopath.ptr, GIT_IGNORE_FILE_INREPO); if (error < 0) goto cleanup; @@ -336,6 +341,7 @@ int git_ignore__for_path( git_repository_attr_cache(repo)->cfg_excl_file); cleanup: + git_buf_free(&infopath); if (error < 0) git_ignore__free(ignores); diff --git a/src/ignore.h b/src/ignore.h index d40bd60f9..876c8e0ea 100644 --- a/src/ignore.h +++ b/src/ignore.h @@ -12,7 +12,7 @@ #include "attr_file.h" #define GIT_IGNORE_FILE ".gitignore" -#define GIT_IGNORE_FILE_INREPO "info/exclude" +#define GIT_IGNORE_FILE_INREPO "exclude" #define GIT_IGNORE_FILE_XDG "ignore" /* The git_ignores structure maintains three sets of ignores: diff --git a/src/repository.c b/src/repository.c index 14ad7a599..ed7038543 100644 --- a/src/repository.c +++ b/src/repository.c @@ -992,7 +992,8 @@ int git_repository_odb__weakptr(git_odb **out, git_repository *repo) git_buf odb_path = GIT_BUF_INIT; git_odb *odb; - if ((error = git_buf_joinpath(&odb_path, repo->commondir, GIT_OBJECTS_DIR)) < 0) + if ((error = git_repository_item_path(&odb_path, repo, + GIT_REPOSITORY_ITEM_OBJECTS)) < 0) return error; error = git_odb_open(&odb, odb_path.ptr); diff --git a/src/submodule.c b/src/submodule.c index 1c17075bf..3007d25df 100644 --- a/src/submodule.c +++ b/src/submodule.c @@ -616,8 +616,10 @@ static int submodule_repo_init( * Old style: sub-repo goes directly into repo//.git/ */ if (use_gitlink) { - error = git_buf_join3( - &repodir, '/', git_repository_path(parent_repo), "modules", path); + error = git_repository_item_path(&repodir, parent_repo, GIT_REPOSITORY_ITEM_MODULES); + if (error < 0) + goto cleanup; + error = git_buf_joinpath(&repodir, repodir.ptr, path); if (error < 0) goto cleanup; @@ -1084,8 +1086,10 @@ static int submodule_repo_create( * /modules// with a gitlink in the * sub-repo workdir directory to that repository. */ - error = git_buf_join3( - &repodir, '/', git_repository_path(parent_repo), "modules", path); + error = git_repository_item_path(&repodir, parent_repo, GIT_REPOSITORY_ITEM_MODULES); + if (error < 0) + goto cleanup; + error = git_buf_joinpath(&repodir, repodir.ptr, path); if (error < 0) goto cleanup; diff --git a/src/transports/local.c b/src/transports/local.c index 87745add5..e24e99860 100644 --- a/src/transports/local.c +++ b/src/transports/local.c @@ -375,7 +375,8 @@ static int local_push( goto on_error; } - if ((error = git_buf_joinpath(&odb_path, git_repository_path(remote_repo), "objects/pack")) < 0) + if ((error = git_repository_item_path(&odb_path, remote_repo, GIT_REPOSITORY_ITEM_OBJECTS)) < 0 + || (error = git_buf_joinpath(&odb_path, odb_path.ptr, "pack")) < 0) goto on_error; error = git_packbuilder_write(push->pb, odb_path.ptr, 0, transfer_to_push_transfer, (void *) cbs); From 79ab3ef69f4905a548bd3a301c348a48454c48f7 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Thu, 15 Oct 2015 15:58:05 +0200 Subject: [PATCH 081/366] repository: introduce is_worktree variable --- include/git2/repository.h | 8 ++++++++ src/repository.c | 11 +++++++++++ src/repository.h | 1 + tests/worktree/open.c | 11 +++++++++++ 4 files changed, 31 insertions(+) diff --git a/include/git2/repository.h b/include/git2/repository.h index 74ce4c795..8cf7e8e0c 100644 --- a/include/git2/repository.h +++ b/include/git2/repository.h @@ -467,6 +467,14 @@ GIT_EXTERN(int) git_repository_set_workdir( */ GIT_EXTERN(int) git_repository_is_bare(git_repository *repo); +/** + * Check if a repository is a linked work tree + * + * @param repo Repo to test + * @return 1 if the repository is a linked work tree, 0 otherwise. + */ +GIT_EXTERN(int) git_repository_is_worktree(git_repository *repo); + /** * Get the configuration file for this repository. * diff --git a/src/repository.c b/src/repository.c index ed7038543..1f8035aed 100644 --- a/src/repository.c +++ b/src/repository.c @@ -254,6 +254,7 @@ int git_repository_new(git_repository **out) GITERR_CHECK_ALLOC(repo); repo->is_bare = 1; + repo->is_worktree = 0; return 0; } @@ -558,6 +559,7 @@ int git_repository_open_bare( /* of course we're bare! */ repo->is_bare = 1; + repo->is_worktree = 0; repo->workdir = NULL; *repo_ptr = repo; @@ -772,6 +774,9 @@ int git_repository_open_ext( GITERR_CHECK_ALLOC(repo->commondir); } + if (repo->path_gitlink && repo->commondir && strcmp(repo->path_gitlink, repo->commondir)) + repo->is_worktree = 1; + /* * We'd like to have the config, but git doesn't particularly * care if it's not there, so we need to deal with that. @@ -2186,6 +2191,12 @@ int git_repository_is_bare(git_repository *repo) return repo->is_bare; } +int git_repository_is_worktree(git_repository *repo) +{ + assert(repo); + return repo->is_worktree; +} + int git_repository_set_bare(git_repository *repo) { int error; diff --git a/src/repository.h b/src/repository.h index 5dc67218f..de9ccb1e8 100644 --- a/src/repository.h +++ b/src/repository.h @@ -138,6 +138,7 @@ struct git_repository { git_array_t(git_buf) reserved_names; unsigned is_bare:1; + unsigned is_worktree:1; unsigned int lru_counter; diff --git a/tests/worktree/open.c b/tests/worktree/open.c index 772f7601f..54a8af4a3 100644 --- a/tests/worktree/open.c +++ b/tests/worktree/open.c @@ -1,4 +1,5 @@ #include "clar_libgit2.h" +#include "repository.h" #include "worktree_helpers.h" #define WORKTREE_PARENT "submodules-worktree-parent" @@ -13,6 +14,9 @@ void test_worktree_open__repository(void) cl_assert(git_repository_path(fixture.worktree) != NULL); cl_assert(git_repository_workdir(fixture.worktree) != NULL); + cl_assert(!fixture.repo->is_worktree); + cl_assert(fixture.worktree->is_worktree); + cleanup_fixture_worktree(&fixture); } @@ -39,6 +43,9 @@ void test_worktree_open__submodule_worktree_parent(void) cl_assert(git_repository_path(fixture.worktree) != NULL); cl_assert(git_repository_workdir(fixture.worktree) != NULL); + cl_assert(!fixture.repo->is_worktree); + cl_assert(fixture.worktree->is_worktree); + cleanup_fixture_worktree(&fixture); } @@ -55,6 +62,10 @@ void test_worktree_open__submodule_worktree_child(void) "submodules/testrepo/.git")); setup_fixture_worktree(&child_fixture); + cl_assert(!parent_fixture.repo->is_worktree); + cl_assert(parent_fixture.worktree->is_worktree); + cl_assert(child_fixture.worktree->is_worktree); + cleanup_fixture_worktree(&child_fixture); cleanup_fixture_worktree(&parent_fixture); } From 71dd086195ff9f83b0225fc523a27807acc11ace Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Thu, 17 Sep 2015 11:40:55 +0200 Subject: [PATCH 082/366] refdb: rename refdb_fs_backend's .path to .gitpath The variable '.path' of the refdb_fs_backend struct becomes confusing regarding the introduction of the git commondir. It does not immediatly become obvious what it should point to. Fix this problem by renaming the variable to `gitpath`, clarifying that it acutally points to the `.git` directory of the repository, in contrast to the commonpath directory, which points to the directory containing shared objects like references and the object store. --- src/refdb_fs.c | 59 +++++++++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/src/refdb_fs.c b/src/refdb_fs.c index e40f48bd5..45a0963fe 100644 --- a/src/refdb_fs.c +++ b/src/refdb_fs.c @@ -55,7 +55,8 @@ typedef struct refdb_fs_backend { git_refdb_backend parent; git_repository *repo; - char *path; + /* path to git directory */ + char *gitpath; git_sortedcache *refcache; int peeling_mode; @@ -77,7 +78,7 @@ static int packed_reload(refdb_fs_backend *backend) git_buf packedrefs = GIT_BUF_INIT; char *scan, *eof, *eol; - if (!backend->path) + if (!backend->gitpath) return 0; error = git_sortedcache_lockandload(backend->refcache, &packedrefs); @@ -238,7 +239,7 @@ static int loose_lookup_to_packfile(refdb_fs_backend *backend, const char *name) /* if we fail to load the loose reference, assume someone changed * the filesystem under us and skip it... */ - if (loose_readbuffer(&ref_file, backend->path, name) < 0) { + if (loose_readbuffer(&ref_file, backend->gitpath, name) < 0) { giterr_clear(); goto done; } @@ -287,7 +288,7 @@ static int _dirent_loose_load(void *payload, git_buf *full_path) return error; } - file_path = full_path->ptr + strlen(backend->path); + file_path = full_path->ptr + strlen(backend->gitpath); return loose_lookup_to_packfile(backend, file_path); } @@ -303,7 +304,7 @@ static int packed_loadloose(refdb_fs_backend *backend) int error; git_buf refs_path = GIT_BUF_INIT; - if (git_buf_joinpath(&refs_path, backend->path, GIT_REFS_DIR) < 0) + if (git_buf_joinpath(&refs_path, backend->gitpath, GIT_REFS_DIR) < 0) return -1; /* @@ -331,7 +332,7 @@ static int refdb_fs_backend__exists( assert(backend); if ((error = packed_reload(backend)) < 0 || - (error = git_buf_joinpath(&ref_path, backend->path, ref_name)) < 0) + (error = git_buf_joinpath(&ref_path, backend->gitpath, ref_name)) < 0) return error; *exists = git_path_isfile(ref_path.ptr) || @@ -373,7 +374,7 @@ static int loose_lookup( if (out) *out = NULL; - if ((error = loose_readbuffer(&ref_file, backend->path, ref_name)) < 0) + if ((error = loose_readbuffer(&ref_file, backend->gitpath, ref_name)) < 0) /* cannot read loose ref file - gah */; else if (git__prefixcmp(git_buf_cstr(&ref_file), GIT_SYMREF) == 0) { const char *target; @@ -484,12 +485,12 @@ static int iter_load_loose_paths(refdb_fs_backend *backend, refdb_fs_iter *iter) git_iterator_options fsit_opts = GIT_ITERATOR_OPTIONS_INIT; const git_index_entry *entry = NULL; - if (!backend->path) /* do nothing if no path for loose refs */ + if (!backend->gitpath) /* do nothing if no gitpath for loose refs */ return 0; fsit_opts.flags = backend->iterator_flags; - if ((error = git_buf_printf(&path, "%s/refs", backend->path)) < 0 || + if ((error = git_buf_printf(&path, "%s/refs", backend->gitpath)) < 0 || (error = git_iterator_for_filesystem(&fsit, path.ptr, &fsit_opts)) < 0) { git_buf_free(&path); return error; @@ -729,10 +730,10 @@ static int loose_lock(git_filebuf *file, refdb_fs_backend *backend, const char * /* Remove a possibly existing empty directory hierarchy * which name would collide with the reference name */ - if ((error = git_futils_rmdir_r(name, backend->path, GIT_RMDIR_SKIP_NONEMPTY)) < 0) + if ((error = git_futils_rmdir_r(name, backend->gitpath, GIT_RMDIR_SKIP_NONEMPTY)) < 0) return error; - if (git_buf_joinpath(&ref_path, backend->path, name) < 0) + if (git_buf_joinpath(&ref_path, backend->gitpath, name) < 0) return -1; error = git_filebuf_open(file, ref_path.ptr, GIT_FILEBUF_FORCE, GIT_REFS_FILE_MODE); @@ -1283,7 +1284,7 @@ static int refdb_fs_backend__delete_tail( } /* If a loose reference exists, remove it from the filesystem */ - if (git_buf_joinpath(&loose_path, backend->path, ref_name) < 0) + if (git_buf_joinpath(&loose_path, backend->gitpath, ref_name) < 0) return -1; @@ -1408,20 +1409,20 @@ static void refdb_fs_backend__free(git_refdb_backend *_backend) assert(backend); git_sortedcache_free(backend->refcache); - git__free(backend->path); + git__free(backend->gitpath); git__free(backend); } -static int setup_namespace(git_buf *path, git_repository *repo) +static int setup_namespace(git_buf *gitpath, git_repository *repo) { char *parts, *start, *end; - /* Not all repositories have a path */ + /* Not all repositories have a gitpath */ if (repo->path_repository == NULL) return 0; /* Load the path to the repo first */ - git_buf_puts(path, repo->path_repository); + git_buf_puts(gitpath, repo->path_repository); /* if the repo is not namespaced, nothing else to do */ if (repo->namespace == NULL) @@ -1438,19 +1439,19 @@ static int setup_namespace(git_buf *path, git_repository *repo) * refs under refs/namespaces/foo/refs/namespaces/bar/ */ while ((start = git__strsep(&end, "/")) != NULL) { - git_buf_printf(path, "refs/namespaces/%s/", start); + git_buf_printf(gitpath, "refs/namespaces/%s/", start); } - git_buf_printf(path, "refs/namespaces/%s/refs", end); + git_buf_printf(gitpath, "refs/namespaces/%s/refs", end); git__free(parts); /* Make sure that the folder with the namespace exists */ - if (git_futils_mkdir_relative(git_buf_cstr(path), repo->path_repository, + if (git_futils_mkdir_relative(git_buf_cstr(gitpath), repo->path_repository, 0777, GIT_MKDIR_PATH, NULL) < 0) return -1; - /* Return root of the namespaced path, i.e. without the trailing '/refs' */ - git_buf_rtruncate_at_char(path, '/'); + /* Return root of the namespaced gitpath, i.e. without the trailing '/refs' */ + git_buf_rtruncate_at_char(gitpath, '/'); return 0; } @@ -1948,7 +1949,7 @@ int git_refdb_backend_fs( git_repository *repository) { int t = 0; - git_buf path = GIT_BUF_INIT; + git_buf gitpath = GIT_BUF_INIT; refdb_fs_backend *backend; backend = git__calloc(1, sizeof(refdb_fs_backend)); @@ -1956,18 +1957,18 @@ int git_refdb_backend_fs( backend->repo = repository; - if (setup_namespace(&path, repository) < 0) + if (setup_namespace(&gitpath, repository) < 0) goto fail; - backend->path = git_buf_detach(&path); + backend->gitpath = git_buf_detach(&gitpath); - if (git_buf_joinpath(&path, backend->path, GIT_PACKEDREFS_FILE) < 0 || + if (git_buf_joinpath(&gitpath, backend->gitpath, GIT_PACKEDREFS_FILE) < 0 || git_sortedcache_new( &backend->refcache, offsetof(struct packref, name), - NULL, NULL, packref_cmp, git_buf_cstr(&path)) < 0) + NULL, NULL, packref_cmp, git_buf_cstr(&gitpath)) < 0) goto fail; - git_buf_free(&path); + git_buf_free(&gitpath); if (!git_repository__cvar(&t, backend->repo, GIT_CVAR_IGNORECASE) && t) { backend->iterator_flags |= GIT_ITERATOR_IGNORE_CASE; @@ -1999,8 +2000,8 @@ int git_refdb_backend_fs( return 0; fail: - git_buf_free(&path); - git__free(backend->path); + git_buf_free(&gitpath); + git__free(backend->gitpath); git__free(backend); return -1; } From e0a6c28eb3977ffb675195878345025025e41a83 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 16 Sep 2015 16:09:24 +0200 Subject: [PATCH 083/366] refdb: introduce commondir awareness The refdb_fs_backend is not aware of the git commondir, which stores common objects like the o bject database and packed/loose refereensces when worktrees are used. Make refdb_fs_backend aware of the common directory by introducing a new commonpath variable that points to the actual common path of the database and using it instead of the gitdir for the mentioned objects. --- src/refdb_fs.c | 34 ++++++++++++++++++---- tests/worktree/refs.c | 68 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+), 6 deletions(-) create mode 100644 tests/worktree/refs.c diff --git a/src/refdb_fs.c b/src/refdb_fs.c index 45a0963fe..cb279d9f9 100644 --- a/src/refdb_fs.c +++ b/src/refdb_fs.c @@ -57,6 +57,8 @@ typedef struct refdb_fs_backend { git_repository *repo; /* path to git directory */ char *gitpath; + /* path to common objects' directory */ + char *commonpath; git_sortedcache *refcache; int peeling_mode; @@ -363,6 +365,14 @@ static const char *loose_parse_symbolic(git_buf *file_content) return refname_start; } +static bool is_per_worktree_ref(const char *ref_name) +{ + return strcmp("HEAD", ref_name) == 0 || + strcmp("FETCH_HEAD", ref_name) == 0 || + strcmp("MERGE_HEAD", ref_name) == 0 || + strcmp("ORIG_HEAD", ref_name) == 0; +} + static int loose_lookup( git_reference **out, refdb_fs_backend *backend, @@ -370,11 +380,17 @@ static int loose_lookup( { git_buf ref_file = GIT_BUF_INIT; int error = 0; + const char *ref_dir; if (out) *out = NULL; - if ((error = loose_readbuffer(&ref_file, backend->gitpath, ref_name)) < 0) + if (is_per_worktree_ref(ref_name)) + ref_dir = backend->gitpath; + else + ref_dir = backend->commonpath; + + if ((error = loose_readbuffer(&ref_file, ref_dir, ref_name)) < 0) /* cannot read loose ref file - gah */; else if (git__prefixcmp(git_buf_cstr(&ref_file), GIT_SYMREF) == 0) { const char *target; @@ -485,12 +501,12 @@ static int iter_load_loose_paths(refdb_fs_backend *backend, refdb_fs_iter *iter) git_iterator_options fsit_opts = GIT_ITERATOR_OPTIONS_INIT; const git_index_entry *entry = NULL; - if (!backend->gitpath) /* do nothing if no gitpath for loose refs */ + if (!backend->commonpath) /* do nothing if no commonpath for loose refs */ return 0; fsit_opts.flags = backend->iterator_flags; - if ((error = git_buf_printf(&path, "%s/refs", backend->gitpath)) < 0 || + if ((error = git_buf_printf(&path, "%s/refs", backend->commonpath)) < 0 || (error = git_iterator_for_filesystem(&fsit, path.ptr, &fsit_opts)) < 0) { git_buf_free(&path); return error; @@ -1410,6 +1426,7 @@ static void refdb_fs_backend__free(git_refdb_backend *_backend) git_sortedcache_free(backend->refcache); git__free(backend->gitpath); + git__free(backend->commonpath); git__free(backend); } @@ -1420,6 +1437,8 @@ static int setup_namespace(git_buf *gitpath, git_repository *repo) /* Not all repositories have a gitpath */ if (repo->path_repository == NULL) return 0; + if (repo->commondir == NULL) + return 0; /* Load the path to the repo first */ git_buf_puts(gitpath, repo->path_repository); @@ -1446,7 +1465,7 @@ static int setup_namespace(git_buf *gitpath, git_repository *repo) git__free(parts); /* Make sure that the folder with the namespace exists */ - if (git_futils_mkdir_relative(git_buf_cstr(gitpath), repo->path_repository, + if (git_futils_mkdir_relative(git_buf_cstr(gitpath), repo->commondir, 0777, GIT_MKDIR_PATH, NULL) < 0) return -1; @@ -1960,9 +1979,11 @@ int git_refdb_backend_fs( if (setup_namespace(&gitpath, repository) < 0) goto fail; - backend->gitpath = git_buf_detach(&gitpath); + backend->gitpath = backend->commonpath = git_buf_detach(&gitpath); + if (repository->commondir) + backend->commonpath = git__strdup(repository->commondir); - if (git_buf_joinpath(&gitpath, backend->gitpath, GIT_PACKEDREFS_FILE) < 0 || + if (git_buf_joinpath(&gitpath, backend->commonpath, GIT_PACKEDREFS_FILE) < 0 || git_sortedcache_new( &backend->refcache, offsetof(struct packref, name), NULL, NULL, packref_cmp, git_buf_cstr(&gitpath)) < 0) @@ -2002,6 +2023,7 @@ int git_refdb_backend_fs( fail: git_buf_free(&gitpath); git__free(backend->gitpath); + git__free(backend->commonpath); git__free(backend); return -1; } diff --git a/tests/worktree/refs.c b/tests/worktree/refs.c new file mode 100644 index 000000000..e08e55372 --- /dev/null +++ b/tests/worktree/refs.c @@ -0,0 +1,68 @@ +#include "clar_libgit2.h" +#include "worktree_helpers.h" + +#define COMMON_REPO "testrepo" +#define WORKTREE_REPO "testrepo-worktree" + +static worktree_fixture fixture = + WORKTREE_FIXTURE_INIT(COMMON_REPO, WORKTREE_REPO); + +void test_worktree_refs__initialize(void) +{ + setup_fixture_worktree(&fixture); +} + +void test_worktree_refs__cleanup(void) +{ + cleanup_fixture_worktree(&fixture); +} + +void test_worktree_refs__list(void) +{ + git_strarray refs, wtrefs; + unsigned i, j; + int error = 0; + + cl_git_pass(git_reference_list(&refs, fixture.repo)); + cl_git_pass(git_reference_list(&wtrefs, fixture.worktree)); + + if (refs.count != wtrefs.count) + { + error = GIT_ERROR; + goto exit; + } + + for (i = 0; i < refs.count; i++) + { + int found = 0; + + for (j = 0; j < wtrefs.count; j++) + { + if (!strcmp(refs.strings[i], wtrefs.strings[j])) + { + found = 1; + break; + } + } + + if (!found) + { + error = GIT_ERROR; + goto exit; + } + } + +exit: + git_strarray_free(&refs); + git_strarray_free(&wtrefs); + cl_git_pass(error); +} + +void test_worktree_refs__read_head(void) +{ + git_reference *head; + + cl_git_pass(git_repository_head(&head, fixture.worktree)); + + git_reference_free(head); +} From e9403024fe65528a4125ae08a89cd5a8f2eb61e2 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Thu, 24 Sep 2015 15:32:26 +0200 Subject: [PATCH 084/366] refdb: look for reflog in commondir --- src/refdb_fs.c | 2 +- tests/worktree/reflog.c | 65 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 tests/worktree/reflog.c diff --git a/src/refdb_fs.c b/src/refdb_fs.c index cb279d9f9..91183cd71 100644 --- a/src/refdb_fs.c +++ b/src/refdb_fs.c @@ -1582,7 +1582,7 @@ static int create_new_reflog_file(const char *filepath) GIT_INLINE(int) retrieve_reflog_path(git_buf *path, git_repository *repo, const char *name) { - return git_buf_join3(path, '/', repo->path_repository, GIT_REFLOG_DIR, name); + return git_buf_join3(path, '/', repo->commondir, GIT_REFLOG_DIR, name); } static int refdb_reflog_fs__ensure_log(git_refdb_backend *_backend, const char *name) diff --git a/tests/worktree/reflog.c b/tests/worktree/reflog.c new file mode 100644 index 000000000..6152eb385 --- /dev/null +++ b/tests/worktree/reflog.c @@ -0,0 +1,65 @@ +#include "clar_libgit2.h" +#include "worktree_helpers.h" + +#include "reflog.h" + +#define COMMON_REPO "testrepo" +#define WORKTREE_REPO "testrepo-worktree" + +#define REFLOG "refs/heads/testrepo-worktree" +#define REFLOG_MESSAGE "reflog message" + +static worktree_fixture fixture = + WORKTREE_FIXTURE_INIT(COMMON_REPO, WORKTREE_REPO); + +void test_worktree_reflog__initialize(void) +{ + setup_fixture_worktree(&fixture); +} + +void test_worktree_reflog__cleanup(void) +{ + cleanup_fixture_worktree(&fixture); +} + +void test_worktree_reflog__read(void) +{ + git_reflog *reflog; + const git_reflog_entry *entry; + + cl_git_pass(git_reflog_read(&reflog, fixture.worktree, REFLOG)); + cl_assert_equal_i(git_reflog_entrycount(reflog), 1); + + entry = git_reflog_entry_byindex(reflog, 0); + cl_assert(entry != NULL); + cl_assert_equal_s(git_reflog_entry_message(entry), "branch: Created from HEAD"); + + git_reflog_free(reflog); +} + +void test_worktree_reflog__append_then_read(void) +{ + git_reflog *reflog, *parent_reflog; + const git_reflog_entry *entry; + git_reference *head; + git_signature *sig; + const git_oid *oid; + + cl_git_pass(git_repository_head(&head, fixture.worktree)); + cl_assert((oid = git_reference_target(head)) != NULL); + cl_git_pass(git_signature_now(&sig, "foo", "foo@bar")); + + cl_git_pass(git_reflog_read(&reflog, fixture.worktree, REFLOG)); + cl_git_pass(git_reflog_append(reflog, oid, sig, REFLOG_MESSAGE)); + git_reflog_write(reflog); + + cl_git_pass(git_reflog_read(&parent_reflog, fixture.repo, REFLOG)); + entry = git_reflog_entry_byindex(parent_reflog, 0); + cl_assert(git_oid_cmp(oid, &entry->oid_old) == 0); + cl_assert(git_oid_cmp(oid, &entry->oid_cur) == 0); + + git_reference_free(head); + git_signature_free(sig); + git_reflog_free(reflog); + git_reflog_free(parent_reflog); +} From 4292837d502fedbbf1f24abe355eb349e4b3b0c9 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Thu, 24 Sep 2015 14:37:10 +0200 Subject: [PATCH 085/366] config: open configuration in commondir A repository's configuartion file can always be found in the GIT_COMMON_DIR, which has been newly introduced. For normal repositories this does change nothing, but for working trees this change allows to access the shared configuration file. --- src/repository.c | 3 +-- tests/worktree/config.c | 45 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 tests/worktree/config.c diff --git a/src/repository.c b/src/repository.c index 1f8035aed..a829161e8 100644 --- a/src/repository.c +++ b/src/repository.c @@ -862,8 +862,7 @@ static int load_config( if ((error = git_config_new(&cfg)) < 0) return error; - error = git_buf_joinpath( - &config_path, repo->path_repository, GIT_CONFIG_FILENAME_INREPO); + error = git_repository_item_path(&config_path, repo, GIT_REPOSITORY_ITEM_CONFIG); if (error < 0) goto on_error; diff --git a/tests/worktree/config.c b/tests/worktree/config.c new file mode 100644 index 000000000..3ab317bb5 --- /dev/null +++ b/tests/worktree/config.c @@ -0,0 +1,45 @@ +#include "clar_libgit2.h" +#include "worktree_helpers.h" + +#define COMMON_REPO "testrepo" +#define WORKTREE_REPO "testrepo-worktree" + +static worktree_fixture fixture = + WORKTREE_FIXTURE_INIT(COMMON_REPO, WORKTREE_REPO); + +void test_worktree_config__initialize(void) +{ + setup_fixture_worktree(&fixture); +} + +void test_worktree_config__cleanup(void) +{ + cleanup_fixture_worktree(&fixture); +} + +void test_worktree_config__open(void) +{ + git_config *cfg; + + cl_git_pass(git_repository_config(&cfg, fixture.worktree)); + cl_assert(cfg != NULL); + + git_config_free(cfg); +} + +void test_worktree_config__set(void) +{ + git_config *cfg; + int32_t val; + + cl_git_pass(git_repository_config(&cfg, fixture.worktree)); + cl_git_pass(git_config_set_int32(cfg, "core.dummy", 5)); + git_config_free(cfg); + + // reopen to verify configuration has been set in the + // common dir + cl_git_pass(git_repository_config(&cfg, fixture.repo)); + cl_git_pass(git_config_get_int32(&val, cfg, "core.dummy")); + cl_assert_equal_i(val, 5); + git_config_free(cfg); +} From 854b5c70e3f8f4701d005cbd0623f0bef8d00060 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Mon, 26 Oct 2015 16:21:09 +0100 Subject: [PATCH 086/366] repository: expose `repo_init_create_head` Expose the function `repo_init_create_head` as `git_repository_create_head`. --- src/repository.c | 4 ++-- src/repository.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/repository.c b/src/repository.c index a829161e8..2e267b72d 100644 --- a/src/repository.c +++ b/src/repository.c @@ -1262,7 +1262,7 @@ static int check_repositoryformatversion(git_config *config) return 0; } -static int repo_init_create_head(const char *git_dir, const char *ref_name) +int git_repository_create_head(const char *git_dir, const char *ref_name) { git_buf ref_path = GIT_BUF_INIT; git_filebuf ref = GIT_FILEBUF_INIT; @@ -1959,7 +1959,7 @@ int git_repository_init_ext( repo_path.ptr, wd, opts)) && !(error = repo_init_config( repo_path.ptr, wd, opts->flags, opts->mode))) - error = repo_init_create_head( + error = git_repository_create_head( repo_path.ptr, opts->initial_head); } if (error < 0) diff --git a/src/repository.h b/src/repository.h index de9ccb1e8..74e15e146 100644 --- a/src/repository.h +++ b/src/repository.h @@ -154,6 +154,7 @@ GIT_INLINE(git_attr_cache *) git_repository_attr_cache(git_repository *repo) } int git_repository_head_tree(git_tree **tree, git_repository *repo); +int git_repository_create_head(const char *git_dir, const char *ref_name); /* * Weak pointers to repository internals. From 45f2b7a43ffe77bac3acbf21a041b56f03842ba8 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 21 Oct 2015 11:48:02 +0200 Subject: [PATCH 087/366] worktree: implement `git_worktree_list` Add new module for working trees with the `git_worktree_list` function. The function lists names for all working trees of a certain repository. --- include/git2/worktree.h | 37 +++++++++++++ src/worktree.c | 58 +++++++++++++++++++++ tests/worktree/worktree.c | 107 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 202 insertions(+) create mode 100644 include/git2/worktree.h create mode 100644 src/worktree.c create mode 100644 tests/worktree/worktree.c diff --git a/include/git2/worktree.h b/include/git2/worktree.h new file mode 100644 index 000000000..c09fa32d0 --- /dev/null +++ b/include/git2/worktree.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ +#ifndef INCLUDE_git_worktree_h__ +#define INCLUDE_git_worktree_h__ + +#include "common.h" +#include "types.h" +#include "strarray.h" + +/** + * @file git2/worktrees.h + * @brief Git worktree related functions + * @defgroup git_commit Git worktree related functions + * @ingroup Git + * @{ + */ +GIT_BEGIN_DECL + +/** + * List names of linked working trees + * + * The returned list should be released with `git_strarray_free` + * when no longer needed. + * + * @param out pointer to the array of working tree names + * @param repo the repo to use when listing working trees + * @return 0 or an error code + */ +GIT_EXTERN(int) git_worktree_list(git_strarray *out, git_repository *repo); + +/** @} */ +GIT_END_DECL +#endif diff --git a/src/worktree.c b/src/worktree.c new file mode 100644 index 000000000..28d895d5c --- /dev/null +++ b/src/worktree.c @@ -0,0 +1,58 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#include "git2/worktree.h" + +#include "common.h" +#include "repository.h" + +static bool is_worktree_dir(git_buf *dir) +{ + return git_path_contains_file(dir, "commondir") + && git_path_contains_file(dir, "gitdir") + && git_path_contains_file(dir, "HEAD"); +} + +int git_worktree_list(git_strarray *wts, git_repository *repo) +{ + git_vector worktrees = GIT_VECTOR_INIT; + git_buf path = GIT_BUF_INIT; + char *worktree; + unsigned i, len; + int error; + + assert(wts && repo); + + wts->count = 0; + wts->strings = NULL; + + if ((error = git_buf_printf(&path, "%s/worktrees/", repo->commondir)) < 0) + goto exit; + if (!git_path_exists(path.ptr) || git_path_is_empty_dir(path.ptr)) + goto exit; + if ((error = git_path_dirload(&worktrees, path.ptr, path.size, 0x0)) < 0) + goto exit; + + len = path.size; + + git_vector_foreach(&worktrees, i, worktree) { + git_buf_truncate(&path, len); + git_buf_puts(&path, worktree); + + if (!is_worktree_dir(&path)) { + git_vector_remove(&worktrees, i); + git__free(worktree); + } + } + + wts->strings = (char **)git_vector_detach(&wts->count, NULL, &worktrees); + +exit: + git_buf_free(&path); + + return error; +} diff --git a/tests/worktree/worktree.c b/tests/worktree/worktree.c new file mode 100644 index 000000000..3acae886e --- /dev/null +++ b/tests/worktree/worktree.c @@ -0,0 +1,107 @@ +#include "clar_libgit2.h" +#include "worktree_helpers.h" + +#include "git2/worktree.h" +#include "repository.h" + +#define COMMON_REPO "testrepo" +#define WORKTREE_REPO "testrepo-worktree" + +static worktree_fixture fixture = + WORKTREE_FIXTURE_INIT(COMMON_REPO, WORKTREE_REPO); + +void test_worktree_worktree__initialize(void) +{ + setup_fixture_worktree(&fixture); +} + +void test_worktree_worktree__cleanup(void) +{ + cleanup_fixture_worktree(&fixture); +} + +void test_worktree_worktree__list(void) +{ + git_strarray wts; + + cl_git_pass(git_worktree_list(&wts, fixture.repo)); + cl_assert_equal_i(wts.count, 1); + cl_assert_equal_s(wts.strings[0], "testrepo-worktree"); + + git_strarray_free(&wts); +} + +void test_worktree_worktree__list_with_invalid_worktree_dirs(void) +{ + const char *filesets[3][2] = { + { "gitdir", "commondir" }, + { "gitdir", "HEAD" }, + { "HEAD", "commondir" }, + }; + git_buf path = GIT_BUF_INIT; + git_strarray wts; + unsigned i, j, len; + + cl_git_pass(git_buf_printf(&path, "%s/worktrees/invalid", + fixture.repo->commondir)); + cl_git_pass(p_mkdir(path.ptr, 0755)); + + len = path.size; + + for (i = 0; i < ARRAY_SIZE(filesets); i++) { + + for (j = 0; j < ARRAY_SIZE(filesets[i]); j++) { + git_buf_truncate(&path, len); + cl_git_pass(git_buf_joinpath(&path, path.ptr, filesets[i][j])); + cl_git_pass(p_close(p_creat(path.ptr, 0644))); + } + + cl_git_pass(git_worktree_list(&wts, fixture.worktree)); + cl_assert_equal_i(wts.count, 1); + cl_assert_equal_s(wts.strings[0], "testrepo-worktree"); + git_strarray_free(&wts); + + for (j = 0; j < ARRAY_SIZE(filesets[i]); j++) { + git_buf_truncate(&path, len); + cl_git_pass(git_buf_joinpath(&path, path.ptr, filesets[i][j])); + p_unlink(path.ptr); + } + } + + git_buf_free(&path); +} + +void test_worktree_worktree__list_in_worktree_repo(void) +{ + git_strarray wts; + + cl_git_pass(git_worktree_list(&wts, fixture.worktree)); + cl_assert_equal_i(wts.count, 1); + cl_assert_equal_s(wts.strings[0], "testrepo-worktree"); + + git_strarray_free(&wts); +} + +void test_worktree_worktree__list_bare(void) +{ + git_repository *repo; + git_strarray wts; + + repo = cl_git_sandbox_init("testrepo.git"); + cl_git_pass(git_worktree_list(&wts, repo)); + cl_assert_equal_i(wts.count, 0); + + git_repository_free(repo); +} + +void test_worktree_worktree__list_without_worktrees(void) +{ + git_repository *repo; + git_strarray wts; + + repo = cl_git_sandbox_init("testrepo2"); + cl_git_pass(git_worktree_list(&wts, repo)); + cl_assert_equal_i(wts.count, 0); + + git_repository_free(repo); +} From d3bc09e81687ca132226e93ce69b9a28b8d3c66b Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 21 Oct 2015 12:02:31 +0200 Subject: [PATCH 088/366] worktree: introduce `struct git_worktree` Introduce a new `struct git_worktree`, which holds information about a possible working tree connected to a repository. Introduce functions to allow opening working trees for a repository. --- include/git2/types.h | 3 ++ include/git2/worktree.h | 17 ++++++++ src/worktree.c | 89 +++++++++++++++++++++++++++++++++++++++ src/worktree.h | 31 ++++++++++++++ tests/worktree/worktree.c | 28 +++++++++++- 5 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 src/worktree.h diff --git a/include/git2/types.h b/include/git2/types.h index 6f41014b3..dfdaa2920 100644 --- a/include/git2/types.h +++ b/include/git2/types.h @@ -104,6 +104,9 @@ typedef struct git_refdb_backend git_refdb_backend; */ typedef struct git_repository git_repository; +/** Representation of a working tree */ +typedef struct git_worktree git_worktree; + /** Representation of a generic object in a repository */ typedef struct git_object git_object; diff --git a/include/git2/worktree.h b/include/git2/worktree.h index c09fa32d0..8313265d5 100644 --- a/include/git2/worktree.h +++ b/include/git2/worktree.h @@ -32,6 +32,23 @@ GIT_BEGIN_DECL */ GIT_EXTERN(int) git_worktree_list(git_strarray *out, git_repository *repo); +/** + * Lookup a working tree by its name for a given repository + * + * @param out Output pointer to looked up worktree or `NULL` + * @param repo The repository containing worktrees + * @param name Name of the working tree to look up + * @return 0 or an error code + */ +GIT_EXTERN(int) git_worktree_lookup(git_worktree **out, git_repository *repo, const char *name); + +/** + * Free a previously allocated worktree + * + * @param wt worktree handle to close. If NULL nothing occurs. + */ +GIT_EXTERN(void) git_worktree_free(git_worktree *wt); + /** @} */ GIT_END_DECL #endif diff --git a/src/worktree.c b/src/worktree.c index 28d895d5c..a0e5d934a 100644 --- a/src/worktree.c +++ b/src/worktree.c @@ -9,6 +9,7 @@ #include "common.h" #include "repository.h" +#include "worktree.h" static bool is_worktree_dir(git_buf *dir) { @@ -56,3 +57,91 @@ exit: return error; } + +static char *read_link(const char *base, const char *file) +{ + git_buf path = GIT_BUF_INIT, buf = GIT_BUF_INIT; + + assert(base && file); + + if (git_buf_joinpath(&path, base, file) < 0) + goto err; + if (git_futils_readbuffer(&buf, path.ptr) < 0) + goto err; + git_buf_free(&path); + + git_buf_rtrim(&buf); + + if (!git_path_is_relative(buf.ptr)) + return git_buf_detach(&buf); + + if (git_buf_sets(&path, base) < 0) + goto err; + if (git_path_apply_relative(&path, buf.ptr) < 0) + goto err; + git_buf_free(&buf); + + return git_buf_detach(&path); + +err: + git_buf_free(&buf); + git_buf_free(&path); + + return NULL; +} + +int git_worktree_lookup(git_worktree **out, git_repository *repo, const char *name) +{ + git_buf path = GIT_BUF_INIT; + git_worktree *wt = NULL; + int error; + + assert(repo && name); + + *out = NULL; + + if ((error = git_buf_printf(&path, "%s/worktrees/%s", repo->commondir, name)) < 0) + goto out; + + if (!is_worktree_dir(&path)) { + error = -1; + goto out; + } + + if ((wt = git__malloc(sizeof(struct git_repository))) == NULL) { + error = -1; + goto out; + } + + if ((wt->name = git__strdup(name)) == NULL + || (wt->commondir_path = read_link(path.ptr, "commondir")) == NULL + || (wt->gitlink_path = read_link(path.ptr, "gitdir")) == NULL + || (wt->parent_path = git__strdup(git_repository_path(repo))) == NULL) { + error = -1; + goto out; + } + wt->gitdir_path = git_buf_detach(&path); + + (*out) = wt; + +out: + git_buf_free(&path); + + if (error) + git_worktree_free(wt); + + return error; +} + +void git_worktree_free(git_worktree *wt) +{ + if (!wt) + return; + + git__free(wt->commondir_path); + git__free(wt->gitlink_path); + git__free(wt->gitdir_path); + git__free(wt->parent_path); + git__free(wt->name); + git__free(wt); +} diff --git a/src/worktree.h b/src/worktree.h new file mode 100644 index 000000000..0e1666c42 --- /dev/null +++ b/src/worktree.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ +#ifndef INCLUDE_worktree_h__ +#define INCLUDE_worktree_h__ + +#include "git2/common.h" +#include "git2/worktree.h" + +struct git_worktree { + /* Name of the working tree. This is the name of the + * containing directory in the `$PARENT/.git/worktrees/` + * directory. */ + char *name; + + /* Path to the .git file in the working tree's repository */ + char *gitlink_path; + /* Path to the .git directory inside the parent's + * worktrees directory */ + char *gitdir_path; + /* Path to the common directory contained in the parent + * repository */ + char *commondir_path; + /* Path to the parent's .git directory */ + char *parent_path; +}; + +#endif diff --git a/tests/worktree/worktree.c b/tests/worktree/worktree.c index 3acae886e..28d88993d 100644 --- a/tests/worktree/worktree.c +++ b/tests/worktree/worktree.c @@ -1,8 +1,8 @@ #include "clar_libgit2.h" #include "worktree_helpers.h" -#include "git2/worktree.h" #include "repository.h" +#include "worktree.h" #define COMMON_REPO "testrepo" #define WORKTREE_REPO "testrepo-worktree" @@ -105,3 +105,29 @@ void test_worktree_worktree__list_without_worktrees(void) git_repository_free(repo); } + +void test_worktree_worktree__lookup(void) +{ + git_worktree *wt; + git_buf gitdir_path = GIT_BUF_INIT; + + cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree")); + + git_buf_printf(&gitdir_path, "%s/worktrees/%s", fixture.repo->commondir, "testrepo-worktree"); + + cl_assert_equal_s(wt->gitdir_path, gitdir_path.ptr); + cl_assert_equal_s(wt->parent_path, fixture.repo->path_repository); + cl_assert_equal_s(wt->gitlink_path, fixture.worktree->path_gitlink); + cl_assert_equal_s(wt->commondir_path, fixture.repo->commondir); + + git_buf_free(&gitdir_path); + git_worktree_free(wt); +} + +void test_worktree_worktree__lookup_nonexistent_worktree(void) +{ + git_worktree *wt; + + cl_git_fail(git_worktree_lookup(&wt, fixture.repo, "nonexistent")); + cl_assert_equal_p(wt, NULL); +} From a6bddf605d7553551fef6b02e6c87408457f3a06 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Mon, 13 Feb 2017 10:34:08 +0100 Subject: [PATCH 089/366] tests: fix permissions on testrepo.git index file --- tests/resources/testrepo.git/index | Bin 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 tests/resources/testrepo.git/index diff --git a/tests/resources/testrepo.git/index b/tests/resources/testrepo.git/index old mode 100755 new mode 100644 From 8c8d726ef784b3f47ed3cd9427202a74563f626e Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 21 Oct 2015 12:10:30 +0200 Subject: [PATCH 090/366] worktree: implement `git_repository_open_from_worktree` Add function `git_repository_open_from_worktree`, which allows to open a `git_worktree` as repository. --- include/git2/repository.h | 11 ++++++ src/repository.c | 31 +++++++++++++++++ tests/worktree/worktree.c | 72 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 114 insertions(+) diff --git a/include/git2/repository.h b/include/git2/repository.h index 8cf7e8e0c..29eb2da49 100644 --- a/include/git2/repository.h +++ b/include/git2/repository.h @@ -35,6 +35,17 @@ GIT_BEGIN_DECL * @return 0 or an error code */ GIT_EXTERN(int) git_repository_open(git_repository **out, const char *path); +/** + * Open working tree as a repository + * + * Open the working directory of the working tree as a normal + * repository that can then be worked on. + * + * @param out Output pointer containing opened repository + * @param wt Working tree to open + * @return 0 or an error code + */ +GIT_EXTERN(int) git_repository_open_from_worktree(git_repository **out, git_worktree *wt); /** * Create a "fake" repository to wrap an object database diff --git a/src/repository.c b/src/repository.c index 2e267b72d..03e43909b 100644 --- a/src/repository.c +++ b/src/repository.c @@ -28,6 +28,7 @@ #include "diff_driver.h" #include "annotated_commit.h" #include "submodule.h" +#include "worktree.h" GIT__USE_STRMAP #include "strmap.h" @@ -817,6 +818,36 @@ int git_repository_open(git_repository **repo_out, const char *path) repo_out, path, GIT_REPOSITORY_OPEN_NO_SEARCH, NULL); } +int git_repository_open_from_worktree(git_repository **repo_out, git_worktree *wt) +{ + git_buf path = GIT_BUF_INIT; + git_repository *repo = NULL; + int len, err; + + assert(repo_out && wt); + + *repo_out = NULL; + len = strlen(wt->gitlink_path); + + if (len <= 4 || strcasecmp(wt->gitlink_path + len - 4, ".git")) { + err = -1; + goto out; + } + + if ((err = git_buf_set(&path, wt->gitlink_path, len - 4)) < 0) + goto out; + + if ((err = git_repository_open(&repo, path.ptr)) < 0) + goto out; + + *repo_out = repo; + +out: + git_buf_free(&path); + + return err; +} + int git_repository_wrap_odb(git_repository **repo_out, git_odb *odb) { git_repository *repo; diff --git a/tests/worktree/worktree.c b/tests/worktree/worktree.c index 28d88993d..d891d6f8f 100644 --- a/tests/worktree/worktree.c +++ b/tests/worktree/worktree.c @@ -131,3 +131,75 @@ void test_worktree_worktree__lookup_nonexistent_worktree(void) cl_git_fail(git_worktree_lookup(&wt, fixture.repo, "nonexistent")); cl_assert_equal_p(wt, NULL); } + +void test_worktree_worktree__open(void) +{ + git_worktree *wt; + git_repository *repo; + + cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree")); + + cl_git_pass(git_repository_open_from_worktree(&repo, wt)); + cl_assert_equal_s(git_repository_workdir(repo), + git_repository_workdir(fixture.worktree)); + + git_repository_free(repo); + git_worktree_free(wt); +} + +void test_worktree_worktree__open_invalid_commondir(void) +{ + git_worktree *wt; + git_repository *repo; + git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT; + + cl_git_pass(git_buf_sets(&buf, "/path/to/nonexistent/commondir")); + cl_git_pass(git_buf_printf(&path, + "%s/worktrees/testrepo-worktree/commondir", + fixture.repo->commondir)); + cl_git_pass(git_futils_writebuffer(&buf, path.ptr, O_RDWR, 0644)); + + cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree")); + cl_git_fail(git_repository_open_from_worktree(&repo, wt)); + + git_buf_free(&buf); + git_buf_free(&path); + git_worktree_free(wt); +} + +void test_worktree_worktree__open_invalid_gitdir(void) +{ + git_worktree *wt; + git_repository *repo; + git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT; + + cl_git_pass(git_buf_sets(&buf, "/path/to/nonexistent/gitdir")); + cl_git_pass(git_buf_printf(&path, + "%s/worktrees/testrepo-worktree/gitdir", + fixture.repo->commondir)); + cl_git_pass(git_futils_writebuffer(&buf, path.ptr, O_RDWR, 0644)); + + cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree")); + cl_git_fail(git_repository_open_from_worktree(&repo, wt)); + + git_buf_free(&buf); + git_buf_free(&path); + git_worktree_free(wt); +} + +void test_worktree_worktree__open_invalid_parent(void) +{ + git_worktree *wt; + git_repository *repo; + git_buf buf = GIT_BUF_INIT; + + cl_git_pass(git_buf_sets(&buf, "/path/to/nonexistent/gitdir")); + cl_git_pass(git_futils_writebuffer(&buf, + fixture.worktree->path_gitlink, O_RDWR, 0644)); + + cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree")); + cl_git_fail(git_repository_open_from_worktree(&repo, wt)); + + git_buf_free(&buf); + git_worktree_free(wt); +} From 372dc9ff6ada409204b7c3de882e5dad16f30b36 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 21 Oct 2015 13:49:55 +0200 Subject: [PATCH 091/366] worktree: implement `git_worktree_validate` Add a new function that checks wether a given `struct git_worktree` is valid. The validation includes checking if the gitdir, parent directory and common directory are present. --- include/git2/errors.h | 1 + include/git2/worktree.h | 12 ++++++++++ src/worktree.c | 38 +++++++++++++++++++++++++++++ tests/worktree/worktree.c | 50 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 101 insertions(+) diff --git a/include/git2/errors.h b/include/git2/errors.h index e959ffd8a..1d271366f 100644 --- a/include/git2/errors.h +++ b/include/git2/errors.h @@ -100,6 +100,7 @@ typedef enum { GITERR_REBASE, GITERR_FILESYSTEM, GITERR_PATCH, + GITERR_WORKTREE } git_error_t; /** diff --git a/include/git2/worktree.h b/include/git2/worktree.h index 8313265d5..c6ca30bcd 100644 --- a/include/git2/worktree.h +++ b/include/git2/worktree.h @@ -49,6 +49,18 @@ GIT_EXTERN(int) git_worktree_lookup(git_worktree **out, git_repository *repo, co */ GIT_EXTERN(void) git_worktree_free(git_worktree *wt); +/** + * Check if worktree is valid + * + * A valid worktree requires both the git data structures inside + * the linked parent repository and the linked working copy to be + * present. + * + * @param wt Worktree to check + * @return 0 when worktree is valid, error-code otherwise + */ +GIT_EXTERN(int) git_worktree_validate(const git_worktree *wt); + /** @} */ GIT_END_DECL #endif diff --git a/src/worktree.c b/src/worktree.c index a0e5d934a..2852c1888 100644 --- a/src/worktree.c +++ b/src/worktree.c @@ -145,3 +145,41 @@ void git_worktree_free(git_worktree *wt) git__free(wt->name); git__free(wt); } + +int git_worktree_validate(const git_worktree *wt) +{ + git_buf buf = GIT_BUF_INIT; + int err = 0; + + assert(wt); + + git_buf_puts(&buf, wt->gitdir_path); + if (!is_worktree_dir(&buf)) { + giterr_set(GITERR_WORKTREE, + "Worktree gitdir ('%s') is not valid", + wt->gitlink_path); + err = -1; + goto out; + } + + if (!git_path_exists(wt->parent_path)) { + giterr_set(GITERR_WORKTREE, + "Worktree parent directory ('%s') does not exist ", + wt->parent_path); + err = -2; + goto out; + } + + if (!git_path_exists(wt->commondir_path)) { + giterr_set(GITERR_WORKTREE, + "Worktree common directory ('%s') does not exist ", + wt->commondir_path); + err = -3; + goto out; + } + +out: + git_buf_free(&buf); + + return err; +} diff --git a/tests/worktree/worktree.c b/tests/worktree/worktree.c index d891d6f8f..7e9cd2528 100644 --- a/tests/worktree/worktree.c +++ b/tests/worktree/worktree.c @@ -203,3 +203,53 @@ void test_worktree_worktree__open_invalid_parent(void) git_buf_free(&buf); git_worktree_free(wt); } + +void test_worktree_worktree__validate(void) +{ + git_worktree *wt; + + cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree")); + cl_git_pass(git_worktree_validate(wt)); + + git_worktree_free(wt); +} + +void test_worktree_worktree__validate_invalid_commondir(void) +{ + git_worktree *wt; + + cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree")); + git__free(wt->commondir_path); + wt->commondir_path = "/path/to/invalid/commondir"; + + cl_git_fail(git_worktree_validate(wt)); + + wt->commondir_path = NULL; + git_worktree_free(wt); +} + +void test_worktree_worktree__validate_invalid_gitdir(void) +{ + git_worktree *wt; + + cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree")); + git__free(wt->gitdir_path); + wt->gitdir_path = "/path/to/invalid/gitdir"; + cl_git_fail(git_worktree_validate(wt)); + + wt->gitdir_path = NULL; + git_worktree_free(wt); +} + +void test_worktree_worktree__validate_invalid_parent(void) +{ + git_worktree *wt; + + cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree")); + git__free(wt->parent_path); + wt->parent_path = "/path/to/invalid/parent"; + cl_git_fail(git_worktree_validate(wt)); + + wt->parent_path = NULL; + git_worktree_free(wt); +} From dea7488e93bdd9a0291d518af58b1cde6d71aca9 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 23 Oct 2015 14:11:44 +0200 Subject: [PATCH 092/366] worktree: implement `git_worktree_add` Implement the `git_worktree_add` function which can be used to create new working trees for a given repository. --- include/git2/worktree.h | 15 ++++++ src/worktree.c | 102 +++++++++++++++++++++++++++++++++++++- tests/worktree/worktree.c | 83 +++++++++++++++++++++++++++++++ 3 files changed, 199 insertions(+), 1 deletion(-) diff --git a/include/git2/worktree.h b/include/git2/worktree.h index c6ca30bcd..4b045eeb8 100644 --- a/include/git2/worktree.h +++ b/include/git2/worktree.h @@ -61,6 +61,21 @@ GIT_EXTERN(void) git_worktree_free(git_worktree *wt); */ GIT_EXTERN(int) git_worktree_validate(const git_worktree *wt); +/** + * Add a new working tree + * + * Add a new working tree for the repository, that is create the + * required data structures inside the repository and check out + * the current HEAD at `path` + * + * @param out Output pointer containing new working tree + * @param repo Repository to create working tree for + * @param name Name of the working tree + * @param path Path to create working tree at + * @return 0 or an error code + */ +GIT_EXTERN(int) git_worktree_add(git_worktree **out, git_repository *repo, const char *name, const char *path); + /** @} */ GIT_END_DECL #endif diff --git a/src/worktree.c b/src/worktree.c index 2852c1888..3c6cfee45 100644 --- a/src/worktree.c +++ b/src/worktree.c @@ -5,9 +5,12 @@ * a Linking Exception. For full terms see the included COPYING file. */ +#include "common.h" + +#include "git2/branch.h" +#include "git2/commit.h" #include "git2/worktree.h" -#include "common.h" #include "repository.h" #include "worktree.h" @@ -90,6 +93,25 @@ err: return NULL; } +static int write_wtfile(const char *base, const char *file, const git_buf *buf) +{ + git_buf path = GIT_BUF_INIT; + int err; + + assert(base && file && buf); + + if ((err = git_buf_joinpath(&path, base, file)) < 0) + goto out; + + if ((err = git_futils_writebuffer(buf, path.ptr, O_CREAT|O_EXCL|O_WRONLY, 0644)) < 0) + goto out; + +out: + git_buf_free(&path); + + return err; +} + int git_worktree_lookup(git_worktree **out, git_repository *repo, const char *name) { git_buf path = GIT_BUF_INIT; @@ -183,3 +205,81 @@ out: return err; } + +int git_worktree_add(git_worktree **out, git_repository *repo, const char *name, const char *worktree) +{ + git_buf path = GIT_BUF_INIT, buf = GIT_BUF_INIT; + git_reference *ref = NULL, *head = NULL; + git_commit *commit = NULL; + git_repository *wt = NULL; + git_checkout_options coopts = GIT_CHECKOUT_OPTIONS_INIT; + int err; + + assert(out && repo && name && worktree); + + *out = NULL; + + /* Create worktree related files in commondir */ + if ((err = git_buf_joinpath(&path, repo->commondir, "worktrees")) < 0) + goto out; + if (!git_path_exists(path.ptr)) + if ((err = git_futils_mkdir(path.ptr, 0755, GIT_MKDIR_EXCL)) < 0) + goto out; + if ((err = git_buf_joinpath(&path, path.ptr, name)) < 0) + goto out; + if ((err = git_futils_mkdir(path.ptr, 0755, GIT_MKDIR_EXCL)) < 0) + goto out; + + /* Create worktree work dir */ + if ((err = git_futils_mkdir(worktree, 0755, GIT_MKDIR_EXCL)) < 0) + goto out; + + /* Create worktree .git file */ + if ((err = git_buf_printf(&buf, "gitdir: %s\n", path.ptr)) < 0) + goto out; + if ((err = write_wtfile(worktree, ".git", &buf)) < 0) + goto out; + + /* Create commondir files */ + if ((err = git_buf_sets(&buf, repo->commondir)) < 0 + || (err = git_buf_putc(&buf, '\n')) < 0 + || (err = write_wtfile(path.ptr, "commondir", &buf)) < 0) + goto out; + if ((err = git_buf_joinpath(&buf, worktree, ".git")) < 0 + || (err = git_buf_putc(&buf, '\n')) < 0 + || (err = write_wtfile(path.ptr, "gitdir", &buf)) < 0) + goto out; + + /* Create new branch */ + if ((err = git_repository_head(&head, repo)) < 0) + goto out; + if ((err = git_commit_lookup(&commit, repo, &head->target.oid)) < 0) + goto out; + if ((err = git_branch_create(&ref, repo, name, commit, false)) < 0) + goto out; + + /* Set worktree's HEAD */ + if ((err = git_repository_create_head(path.ptr, name)) < 0) + goto out; + if ((err = git_repository_open(&wt, worktree)) < 0) + goto out; + + /* Checkout worktree's HEAD */ + coopts.checkout_strategy = GIT_CHECKOUT_FORCE; + if ((err = git_checkout_head(wt, &coopts)) < 0) + goto out; + + /* Load result */ + if ((err = git_worktree_lookup(out, repo, name)) < 0) + goto out; + +out: + git_buf_free(&path); + git_buf_free(&buf); + git_reference_free(ref); + git_reference_free(head); + git_commit_free(commit); + git_repository_free(wt); + + return err; +} diff --git a/tests/worktree/worktree.c b/tests/worktree/worktree.c index 7e9cd2528..8154baa32 100644 --- a/tests/worktree/worktree.c +++ b/tests/worktree/worktree.c @@ -204,6 +204,89 @@ void test_worktree_worktree__open_invalid_parent(void) git_worktree_free(wt); } +void test_worktree_worktree__init(void) +{ + git_worktree *wt; + git_repository *repo; + git_reference *branch; + git_buf path = GIT_BUF_INIT; + + cl_git_pass(git_buf_joinpath(&path, fixture.repo->workdir, "../worktree-new")); + cl_git_pass(git_worktree_add(&wt, fixture.repo, "worktree-new", path.ptr)); + + /* Open and verify created repo */ + cl_git_pass(git_repository_open(&repo, path.ptr)); + cl_git_pass(git_branch_lookup(&branch, repo, "worktree-new", GIT_BRANCH_LOCAL)); + + git_buf_free(&path); + git_worktree_free(wt); + git_reference_free(branch); + git_repository_free(repo); +} + +void test_worktree_worktree__init_existing_branch(void) +{ + git_reference *head, *branch; + git_commit *commit; + git_worktree *wt; + git_buf path = GIT_BUF_INIT; + + cl_git_pass(git_repository_head(&head, fixture.repo)); + cl_git_pass(git_commit_lookup(&commit, fixture.repo, &head->target.oid)); + cl_git_pass(git_branch_create(&branch, fixture.repo, "worktree-new", commit, false)); + + cl_git_pass(git_buf_joinpath(&path, fixture.repo->workdir, "../worktree-new")); + cl_git_fail(git_worktree_add(&wt, fixture.repo, "worktree-new", path.ptr)); + + git_buf_free(&path); + git_commit_free(commit); + git_reference_free(head); + git_reference_free(branch); +} + +void test_worktree_worktree__init_existing_worktree(void) +{ + git_worktree *wt; + git_buf path = GIT_BUF_INIT; + + cl_git_pass(git_buf_joinpath(&path, fixture.repo->workdir, "../worktree-new")); + cl_git_fail(git_worktree_add(&wt, fixture.repo, "testrepo-worktree", path.ptr)); + + cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree")); + cl_assert_equal_s(wt->gitlink_path, fixture.worktree->path_gitlink); + + git_buf_free(&path); + git_worktree_free(wt); +} + +void test_worktree_worktree__init_existing_path(void) +{ + const char *wtfiles[] = { "HEAD", "commondir", "gitdir", "index" }; + git_worktree *wt; + git_buf path = GIT_BUF_INIT; + unsigned i; + + /* Delete files to verify they have not been created by + * the init call */ + for (i = 0; i < ARRAY_SIZE(wtfiles); i++) { + cl_git_pass(git_buf_joinpath(&path, + fixture.worktree->path_repository, wtfiles[i])); + cl_git_pass(p_unlink(path.ptr)); + } + + cl_git_pass(git_buf_joinpath(&path, fixture.repo->workdir, "../testrepo-worktree")); + cl_git_fail(git_worktree_add(&wt, fixture.repo, "worktree-new", path.ptr)); + + /* Verify files have not been re-created */ + for (i = 0; i < ARRAY_SIZE(wtfiles); i++) { + cl_git_pass(git_buf_joinpath(&path, + fixture.worktree->path_repository, wtfiles[i])); + cl_assert(!git_path_exists(path.ptr)); + } + + git_buf_free(&path); +} + void test_worktree_worktree__validate(void) { git_worktree *wt; From 2a503485fae6c93c76bd0465c8b3fad5d9e19f6d Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 21 Oct 2015 16:03:04 +0200 Subject: [PATCH 093/366] worktree: implement locking mechanisms Working trees support locking by creating a file `locked` inside the tree's gitdir with an optional reason inside. Support this feature by adding functions to get and set the locking status. --- include/git2/worktree.h | 36 +++++++++++++++++++ src/worktree.c | 73 +++++++++++++++++++++++++++++++++++++++ src/worktree.h | 2 ++ tests/worktree/worktree.c | 59 +++++++++++++++++++++++++++++++ 4 files changed, 170 insertions(+) diff --git a/include/git2/worktree.h b/include/git2/worktree.h index 4b045eeb8..62b4b5e79 100644 --- a/include/git2/worktree.h +++ b/include/git2/worktree.h @@ -8,6 +8,7 @@ #define INCLUDE_git_worktree_h__ #include "common.h" +#include "buffer.h" #include "types.h" #include "strarray.h" @@ -76,6 +77,41 @@ GIT_EXTERN(int) git_worktree_validate(const git_worktree *wt); */ GIT_EXTERN(int) git_worktree_add(git_worktree **out, git_repository *repo, const char *name, const char *path); +/* + * Lock worktree if not already locked + * + * Lock a worktree, optionally specifying a reason why the linked + * working tree is being locked. + * + * @param wt Worktree to lock + * @param reason Reason why the working tree is being locked + * @return 0 on success, non-zero otherwise + */ +GIT_EXTERN(int) git_worktree_lock(git_worktree *wt, char *reason); + +/** + * Unlock a locked worktree + * + * @param wt Worktree to unlock + * @return 0 on success, 1 if worktree was not locked, error-code + * otherwise + */ +GIT_EXTERN(int) git_worktree_unlock(git_worktree *wt); + +/** + * Check if worktree is locked + * + * A worktree may be locked if the linked working tree is stored + * on a portable device which is not available. + * + * @param reason Buffer to store reason in. If NULL no reason is stored. + * @param wt Worktree to check + * @return 0 when the working tree not locked, a value greater + * than zero if it is locked, less than zero if there was an + * error + */ +GIT_EXTERN(int) git_worktree_is_locked(git_buf *reason, const git_worktree *wt); + /** @} */ GIT_END_DECL #endif diff --git a/src/worktree.c b/src/worktree.c index 3c6cfee45..fa5a916c0 100644 --- a/src/worktree.c +++ b/src/worktree.c @@ -143,6 +143,7 @@ int git_worktree_lookup(git_worktree **out, git_repository *repo, const char *na goto out; } wt->gitdir_path = git_buf_detach(&path); + wt->locked = !!git_worktree_is_locked(NULL, wt); (*out) = wt; @@ -283,3 +284,75 @@ out: return err; } + +int git_worktree_lock(git_worktree *wt, char *creason) +{ + git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT; + int err; + + assert(wt); + + if ((err = git_worktree_is_locked(NULL, wt)) < 0) + goto out; + + if ((err = git_buf_joinpath(&path, wt->gitdir_path, "locked")) < 0) + goto out; + + if (creason) + git_buf_attach_notowned(&buf, creason, strlen(creason)); + + if ((err = git_futils_writebuffer(&buf, path.ptr, O_CREAT|O_EXCL|O_WRONLY, 0644)) < 0) + goto out; + + wt->locked = 1; + +out: + git_buf_free(&path); + + return err; +} + +int git_worktree_unlock(git_worktree *wt) +{ + git_buf path = GIT_BUF_INIT; + + assert(wt); + + if (!git_worktree_is_locked(NULL, wt)) + return 0; + + if (git_buf_joinpath(&path, wt->gitdir_path, "locked") < 0) + return -1; + + if (p_unlink(path.ptr) != 0) { + git_buf_free(&path); + return -1; + } + + wt->locked = 0; + + git_buf_free(&path); + + return 0; +} + +int git_worktree_is_locked(git_buf *reason, const git_worktree *wt) +{ + git_buf path = GIT_BUF_INIT; + int ret; + + assert(wt); + + if (reason) + git_buf_clear(reason); + + if ((ret = git_buf_joinpath(&path, wt->gitdir_path, "locked")) < 0) + goto out; + if ((ret = git_path_exists(path.ptr)) && reason) + git_futils_readbuffer(reason, path.ptr); + +out: + git_buf_free(&path); + + return ret; +} diff --git a/src/worktree.h b/src/worktree.h index 0e1666c42..0e1a88d98 100644 --- a/src/worktree.h +++ b/src/worktree.h @@ -26,6 +26,8 @@ struct git_worktree { char *commondir_path; /* Path to the parent's .git directory */ char *parent_path; + + int locked:1; }; #endif diff --git a/tests/worktree/worktree.c b/tests/worktree/worktree.c index 8154baa32..82b4ebc0d 100644 --- a/tests/worktree/worktree.c +++ b/tests/worktree/worktree.c @@ -336,3 +336,62 @@ void test_worktree_worktree__validate_invalid_parent(void) wt->parent_path = NULL; git_worktree_free(wt); } + +void test_worktree_worktree__lock_with_reason(void) +{ + git_worktree *wt; + git_buf reason = GIT_BUF_INIT; + + cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree")); + + cl_assert(!git_worktree_is_locked(NULL, wt)); + cl_git_pass(git_worktree_lock(wt, "because")); + cl_assert(git_worktree_is_locked(&reason, wt) > 0); + cl_assert_equal_s(reason.ptr, "because"); + cl_assert(wt->locked); + + git_buf_free(&reason); + git_worktree_free(wt); +} + +void test_worktree_worktree__lock_without_reason(void) +{ + git_worktree *wt; + git_buf reason = GIT_BUF_INIT; + + cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree")); + + cl_assert(!git_worktree_is_locked(NULL, wt)); + cl_git_pass(git_worktree_lock(wt, NULL)); + cl_assert(git_worktree_is_locked(&reason, wt) > 0); + cl_assert_equal_i(reason.size, 0); + cl_assert(wt->locked); + + git_buf_free(&reason); + git_worktree_free(wt); +} + +void test_worktree_worktree__unlock_unlocked_worktree(void) +{ + git_worktree *wt; + + cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree")); + cl_assert(!git_worktree_is_locked(NULL, wt)); + cl_assert(git_worktree_unlock(wt) == 0); + cl_assert(!wt->locked); + + git_worktree_free(wt); +} + +void test_worktree_worktree__unlock_locked_worktree(void) +{ + git_worktree *wt; + + cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree")); + cl_git_pass(git_worktree_lock(wt, NULL)); + cl_assert(git_worktree_is_locked(NULL, wt)); + cl_git_pass(git_worktree_unlock(wt)); + cl_assert(!wt->locked); + + git_worktree_free(wt); +} From f0cfc34105fd68af9eb6e2024459c40c45e7d3a0 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 21 Oct 2015 13:53:18 +0200 Subject: [PATCH 094/366] worktree: implement `git_worktree_prune` Implement the `git_worktree_prune` function. This function can be used to delete working trees from a repository. According to the flags passed to it, it can either delete the working tree's gitdir only or both gitdir and the working directory. --- include/git2/worktree.h | 26 ++++++++++++++++ src/worktree.c | 64 +++++++++++++++++++++++++++++++++++++++ tests/worktree/worktree.c | 58 +++++++++++++++++++++++++++++++++++ 3 files changed, 148 insertions(+) diff --git a/include/git2/worktree.h b/include/git2/worktree.h index 62b4b5e79..594ff795b 100644 --- a/include/git2/worktree.h +++ b/include/git2/worktree.h @@ -112,6 +112,32 @@ GIT_EXTERN(int) git_worktree_unlock(git_worktree *wt); */ GIT_EXTERN(int) git_worktree_is_locked(git_buf *reason, const git_worktree *wt); +/** + * Flags which can be passed to git_worktree_prune to alter its + * behavior. + */ +typedef enum { + /* Prune working tree even if working tree is valid */ + GIT_WORKTREE_PRUNE_VALID = 1u << 0, + /* Prune working tree even if it is locked */ + GIT_WORKTREE_PRUNE_LOCKED = 1u << 1, + /* Prune checked out working tree */ + GIT_WORKTREE_PRUNE_WORKING_TREE = 1u << 2, +} git_worktree_prune_t; + +/** + * Prune working tree + * + * Prune the working tree, that is remove the git data + * structures on disk. The repository will only be pruned of + * `git_worktree_is_prunable` succeeds. + * + * @param wt Worktree to prune + * @param flags git_worktree_prune_t flags + * @return 0 or an error code + */ +GIT_EXTERN(int) git_worktree_prune(git_worktree *wt, unsigned flags); + /** @} */ GIT_END_DECL #endif diff --git a/src/worktree.c b/src/worktree.c index fa5a916c0..95a2757fe 100644 --- a/src/worktree.c +++ b/src/worktree.c @@ -356,3 +356,67 @@ out: return ret; } + +int git_worktree_prune(git_worktree *wt, unsigned flags) +{ + git_buf reason = GIT_BUF_INIT, path = GIT_BUF_INIT; + char *wtpath; + int err; + + if ((flags & GIT_WORKTREE_PRUNE_LOCKED) == 0 && + git_worktree_is_locked(&reason, wt)) + { + if (!reason.size) + git_buf_attach_notowned(&reason, "no reason given", 15); + giterr_set(GITERR_WORKTREE, "Not pruning locked working tree: '%s'", reason.ptr); + + err = -1; + goto out; + } + + if ((flags & GIT_WORKTREE_PRUNE_VALID) == 0 && + git_worktree_validate(wt) == 0) + { + giterr_set(GITERR_WORKTREE, "Not pruning valid working tree"); + err = -1; + goto out; + } + + /* Delete gitdir in parent repository */ + if ((err = git_buf_printf(&path, "%s/worktrees/%s", wt->parent_path, wt->name)) < 0) + goto out; + if (!git_path_exists(path.ptr)) + { + giterr_set(GITERR_WORKTREE, "Worktree gitdir '%s' does not exist", path.ptr); + err = -1; + goto out; + } + if ((err = git_futils_rmdir_r(path.ptr, NULL, GIT_RMDIR_REMOVE_FILES)) < 0) + goto out; + + /* Skip deletion of the actual working tree if it does + * not exist or deletion was not requested */ + if ((flags & GIT_WORKTREE_PRUNE_WORKING_TREE) == 0 || + !git_path_exists(wt->gitlink_path)) + { + goto out; + } + + if ((wtpath = git_path_dirname(wt->gitlink_path)) == NULL) + goto out; + git_buf_attach(&path, wtpath, 0); + if (!git_path_exists(path.ptr)) + { + giterr_set(GITERR_WORKTREE, "Working tree '%s' does not exist", path.ptr); + err = -1; + goto out; + } + if ((err = git_futils_rmdir_r(path.ptr, NULL, GIT_RMDIR_REMOVE_FILES)) < 0) + goto out; + +out: + git_buf_free(&reason); + git_buf_free(&path); + + return err; +} diff --git a/tests/worktree/worktree.c b/tests/worktree/worktree.c index 82b4ebc0d..7758b1b1c 100644 --- a/tests/worktree/worktree.c +++ b/tests/worktree/worktree.c @@ -395,3 +395,61 @@ void test_worktree_worktree__unlock_locked_worktree(void) git_worktree_free(wt); } + +void test_worktree_worktree__prune_valid(void) +{ + git_worktree *wt; + git_repository *repo; + + cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree")); + cl_git_pass(git_worktree_prune(wt, GIT_WORKTREE_PRUNE_VALID)); + + /* Assert the repository is not valid anymore */ + cl_git_fail(git_repository_open_from_worktree(&repo, wt)); + + git_worktree_free(wt); + git_repository_free(repo); +} + +void test_worktree_worktree__prune_locked(void) +{ + git_worktree *wt; + git_repository *repo; + + cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree")); + cl_git_pass(git_worktree_lock(wt, NULL)); + cl_git_fail(git_worktree_prune(wt, GIT_WORKTREE_PRUNE_VALID)); + cl_git_fail(git_worktree_prune(wt, ~GIT_WORKTREE_PRUNE_LOCKED)); + + /* Assert the repository is still valid */ + cl_git_pass(git_repository_open_from_worktree(&repo, wt)); + + git_worktree_free(wt); + git_repository_free(repo); +} + +void test_worktree_worktree__prune_gitdir(void) +{ + git_worktree *wt; + + cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree")); + cl_git_pass(git_worktree_prune(wt, GIT_WORKTREE_PRUNE_VALID)); + + cl_assert(!git_path_exists(wt->gitdir_path)); + cl_assert(git_path_exists(wt->gitlink_path)); + + git_worktree_free(wt); +} + +void test_worktree_worktree__prune_both(void) +{ + git_worktree *wt; + + cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree")); + cl_git_pass(git_worktree_prune(wt, GIT_WORKTREE_PRUNE_WORKING_TREE | GIT_WORKTREE_PRUNE_VALID)); + + cl_assert(!git_path_exists(wt->gitdir_path)); + cl_assert(!git_path_exists(wt->gitlink_path)); + + git_worktree_free(wt); +} From 04fb12abb24810391fa19af5696eb38629d650df Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Tue, 27 Oct 2015 12:37:51 +0100 Subject: [PATCH 095/366] worktree: implement functions reading HEAD Implement `git_repository_head_for_worktree` and `git_repository_head_detached_for_worktree` for directly accessing a worktree's HEAD without opening it as a `git_repository` first. --- include/git2/repository.h | 25 +++++++++++ include/git2/worktree.h | 2 +- src/repository.c | 85 +++++++++++++++++++++++++++++++++++++ tests/worktree/repository.c | 63 +++++++++++++++++++++++++++ tests/worktree/worktree.c | 1 + 5 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 tests/worktree/repository.c diff --git a/include/git2/repository.h b/include/git2/repository.h index 29eb2da49..a396a5409 100644 --- a/include/git2/repository.h +++ b/include/git2/repository.h @@ -345,6 +345,17 @@ GIT_EXTERN(int) git_repository_init_ext( */ GIT_EXTERN(int) git_repository_head(git_reference **out, git_repository *repo); +/** + * Retrieve the referenced HEAD for the worktree + * + * @param out pointer to the reference which will be retrieved + * @param repo a repository object + * @param name name of the worktree to retrieve HEAD for + * @return 0 when successful, error-code otherwise + */ +GIT_EXTERN(int) git_repository_head_for_worktree(git_reference **out, git_repository *repo, + const char *name); + /** * Check if a repository's HEAD is detached * @@ -357,6 +368,20 @@ GIT_EXTERN(int) git_repository_head(git_reference **out, git_repository *repo); */ GIT_EXTERN(int) git_repository_head_detached(git_repository *repo); +/* + * Check if a worktree's HEAD is detached + * + * A worktree's HEAD is detached when it points directly to a + * commit instead of a branch. + * + * @param repo a repository object + * @param name name of the worktree to retrieve HEAD for + * @return 1 if HEAD is detached, 0 if its not; error code if + * there was an error + */ +GIT_EXTERN(int) git_repository_head_detached_for_worktree(git_repository *repo, + const char *name); + /** * Check if the current branch is unborn * diff --git a/include/git2/worktree.h b/include/git2/worktree.h index 594ff795b..ec869fb59 100644 --- a/include/git2/worktree.h +++ b/include/git2/worktree.h @@ -77,7 +77,7 @@ GIT_EXTERN(int) git_worktree_validate(const git_worktree *wt); */ GIT_EXTERN(int) git_worktree_add(git_worktree **out, git_repository *repo, const char *name, const char *path); -/* +/** * Lock worktree if not already locked * * Lock a worktree, optionally specifying a reason why the linked diff --git a/src/repository.c b/src/repository.c index 03e43909b..445005e96 100644 --- a/src/repository.c +++ b/src/repository.c @@ -2032,6 +2032,49 @@ int git_repository_head_detached(git_repository *repo) return exists; } +static int read_worktree_head(git_buf *out, git_repository *repo, const char *name) +{ + git_buf path = GIT_BUF_INIT; + int err; + + assert(out && repo && name); + + git_buf_clear(out); + + if ((err = git_buf_printf(&path, "%s/worktrees/%s/HEAD", repo->commondir, name)) < 0) + goto out; + if (!git_path_exists(path.ptr)) + { + err = -1; + goto out; + } + + if ((err = git_futils_readbuffer(out, path.ptr)) < 0) + goto out; + git_buf_rtrim(out); + +out: + git_buf_free(&path); + + return err; +} + +int git_repository_head_detached_for_worktree(git_repository *repo, const char *name) +{ + git_buf buf = GIT_BUF_INIT; + int ret; + + assert(repo && name); + + if (read_worktree_head(&buf, repo, name) < 0) + return -1; + + ret = git__strncmp(buf.ptr, GIT_SYMREF, strlen(GIT_SYMREF)) != 0; + git_buf_free(&buf); + + return ret; +} + int git_repository_head(git_reference **head_out, git_repository *repo) { git_reference *head; @@ -2051,6 +2094,48 @@ int git_repository_head(git_reference **head_out, git_repository *repo) return error == GIT_ENOTFOUND ? GIT_EUNBORNBRANCH : error; } +int git_repository_head_for_worktree(git_reference **out, git_repository *repo, const char *name) +{ + git_buf buf = GIT_BUF_INIT; + git_reference *head; + int err; + + assert(out && repo && name); + + *out = NULL; + + if (git_repository_head_detached_for_worktree(repo, name)) + return -1; + if ((err = read_worktree_head(&buf, repo, name)) < 0) + goto out; + + /* We can only resolve symbolic references */ + if (git__strncmp(buf.ptr, GIT_SYMREF, strlen(GIT_SYMREF))) + { + err = -1; + goto out; + } + git_buf_consume(&buf, buf.ptr + strlen(GIT_SYMREF)); + + if ((err = git_reference_lookup(&head, repo, buf.ptr)) < 0) + goto out; + if (git_reference_type(head) == GIT_REF_OID) + { + *out = head; + err = 0; + goto out; + } + + err = git_reference_lookup_resolved( + out, repo, git_reference_symbolic_target(head), -1); + git_reference_free(head); + +out: + git_buf_free(&buf); + + return err; +} + int git_repository_head_unborn(git_repository *repo) { git_reference *ref = NULL; diff --git a/tests/worktree/repository.c b/tests/worktree/repository.c new file mode 100644 index 000000000..5c7595c64 --- /dev/null +++ b/tests/worktree/repository.c @@ -0,0 +1,63 @@ +#include "clar_libgit2.h" +#include "worktree_helpers.h" +#include "submodule/submodule_helpers.h" + +#include "repository.h" + +#define COMMON_REPO "testrepo" +#define WORKTREE_REPO "testrepo-worktree" + +static worktree_fixture fixture = + WORKTREE_FIXTURE_INIT(COMMON_REPO, WORKTREE_REPO); + +void test_worktree_repository__initialize(void) +{ + setup_fixture_worktree(&fixture); +} + +void test_worktree_repository__cleanup(void) +{ + cleanup_fixture_worktree(&fixture); +} + +void test_worktree_repository__head(void) +{ + git_reference *ref, *head; + + cl_git_pass(git_reference_lookup(&ref, fixture.repo, "refs/heads/testrepo-worktree")); + cl_git_pass(git_repository_head_for_worktree(&head, fixture.repo, "testrepo-worktree")); + cl_assert(git_reference_cmp(ref, head) == 0); + + git_reference_free(ref); + git_reference_free(head); +} + +void test_worktree_repository__head_fails_for_invalid_worktree(void) +{ + git_reference *head = NULL; + + cl_git_fail(git_repository_head_for_worktree(&head, fixture.repo, "invalid")); + cl_assert(head == NULL); +} + +void test_worktree_repository__head_detached(void) +{ + git_reference *ref, *head; + + cl_git_pass(git_reference_lookup(&ref, fixture.repo, "refs/heads/testrepo-worktree")); + cl_git_pass(git_repository_set_head_detached(fixture.worktree, &ref->target.oid)); + + cl_assert(git_repository_head_detached(fixture.worktree)); + cl_assert(git_repository_head_detached_for_worktree(fixture.repo, "testrepo-worktree")); + cl_git_fail(git_repository_head_for_worktree(&head, fixture.repo, "testrepo-worktree")); + + git_reference_free(ref); +} + +void test_worktree_repository__head_detached_fails_for_invalid_worktree(void) +{ + git_reference *head = NULL; + + cl_git_fail(git_repository_head_detached_for_worktree(fixture.repo, "invalid")); + cl_assert(head == NULL); +} diff --git a/tests/worktree/worktree.c b/tests/worktree/worktree.c index 7758b1b1c..756cf387b 100644 --- a/tests/worktree/worktree.c +++ b/tests/worktree/worktree.c @@ -1,6 +1,7 @@ #include "clar_libgit2.h" #include "worktree_helpers.h" +#include "checkout.h" #include "repository.h" #include "worktree.h" From 4321595dcb83131675c7b38ac7fec8337476026e Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Tue, 10 Nov 2015 16:54:48 +0100 Subject: [PATCH 096/366] worktree: test basic merge functionality --- tests/worktree/merge.c | 121 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 tests/worktree/merge.c diff --git a/tests/worktree/merge.c b/tests/worktree/merge.c new file mode 100644 index 000000000..8221e4fc1 --- /dev/null +++ b/tests/worktree/merge.c @@ -0,0 +1,121 @@ +#include "clar_libgit2.h" + +#include "worktree_helpers.h" +#include "merge/merge_helpers.h" + +#define COMMON_REPO "testrepo" +#define WORKTREE_REPO "testrepo-worktree" + +#define MASTER_BRANCH "refs/heads/master" +#define CONFLICT_BRANCH "refs/heads/merge-conflict" + +#define CONFLICT_BRANCH_FILE_TXT \ + "<<<<<<< HEAD\n" \ + "hi\n" \ + "bye!\n" \ + "=======\n" \ + "conflict\n" \ + ">>>>>>> merge-conflict\n" \ + +static worktree_fixture fixture = + WORKTREE_FIXTURE_INIT(COMMON_REPO, WORKTREE_REPO); + +static const char *merge_files[] = { + GIT_MERGE_HEAD_FILE, + GIT_ORIG_HEAD_FILE, + GIT_MERGE_MODE_FILE, + GIT_MERGE_MSG_FILE, +}; + +void test_worktree_merge__initialize(void) +{ + setup_fixture_worktree(&fixture); +} + +void test_worktree_merge__cleanup(void) +{ + cleanup_fixture_worktree(&fixture); +} + +void test_worktree_merge__merge_head(void) +{ + git_reference *theirs_ref, *ref; + git_annotated_commit *theirs; + + cl_git_pass(git_reference_lookup(&theirs_ref, fixture.worktree, CONFLICT_BRANCH)); + cl_git_pass(git_annotated_commit_from_ref(&theirs, fixture.worktree, theirs_ref)); + cl_git_pass(git_merge(fixture.worktree, (const git_annotated_commit **)&theirs, 1, NULL, NULL)); + + cl_git_pass(git_reference_lookup(&ref, fixture.worktree, GIT_MERGE_HEAD_FILE)); + + git_reference_free(ref); + git_reference_free(theirs_ref); + git_annotated_commit_free(theirs); +} + +void test_worktree_merge__merge_setup(void) +{ + git_reference *ours_ref, *theirs_ref; + git_annotated_commit *ours, *theirs; + git_buf path = GIT_BUF_INIT; + unsigned i; + + cl_git_pass(git_reference_lookup(&ours_ref, fixture.worktree, MASTER_BRANCH)); + cl_git_pass(git_annotated_commit_from_ref(&ours, fixture.worktree, ours_ref)); + + cl_git_pass(git_reference_lookup(&theirs_ref, fixture.worktree, CONFLICT_BRANCH)); + cl_git_pass(git_annotated_commit_from_ref(&theirs, fixture.worktree, theirs_ref)); + + cl_git_pass(git_merge__setup(fixture.worktree, + ours, (const git_annotated_commit **)&theirs, 1)); + + for (i = 0; i < ARRAY_SIZE(merge_files); i++) { + git_buf_clear(&path); + cl_git_pass(git_buf_printf(&path, "%s/%s", + fixture.worktree->path_repository, merge_files[i])); + cl_assert(git_path_exists(path.ptr)); + } + + git_buf_free(&path); + git_reference_free(ours_ref); + git_reference_free(theirs_ref); + git_annotated_commit_free(ours); + git_annotated_commit_free(theirs); +} + +void test_worktree_merge__merge_conflict(void) +{ + git_buf path = GIT_BUF_INIT, buf = GIT_BUF_INIT; + git_reference *theirs_ref; + git_annotated_commit *theirs; + git_index *index; + const git_index_entry *entry; + size_t i, conflicts = 0; + + cl_git_pass(git_reference_lookup(&theirs_ref, fixture.worktree, CONFLICT_BRANCH)); + cl_git_pass(git_annotated_commit_from_ref(&theirs, fixture.worktree, theirs_ref)); + + cl_git_pass(git_merge(fixture.worktree, + (const git_annotated_commit **)&theirs, 1, NULL, NULL)); + + cl_git_pass(git_repository_index(&index, fixture.worktree)); + for (i = 0; i < git_index_entrycount(index); i++) { + cl_assert(entry = git_index_get_byindex(index, i)); + + if (git_index_entry_is_conflict(entry)) + conflicts++; + } + cl_assert_equal_sz(conflicts, 3); + + git_reference_free(theirs_ref); + git_annotated_commit_free(theirs); + git_index_free(index); + + cl_git_pass(git_buf_joinpath(&path, fixture.worktree->workdir, "branch_file.txt")); + cl_git_pass(git_futils_readbuffer(&buf, path.ptr)); + cl_assert_equal_s(buf.ptr, CONFLICT_BRANCH_FILE_TXT); + + git_buf_free(&path); + git_buf_free(&buf); +} + From e3acd37b70dc6d8f1ff256b99a26b4e0f13701ef Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 6 Nov 2015 12:08:15 +0100 Subject: [PATCH 097/366] branch: implement `git_branch_is_checked_out` Implement a new function that is able to determine if a branch is checked out in any repository connected to the current repository. In particular, this is required to check if for a given repository and branch, there exists any working tree connected to that repository that is referencing this branch. --- include/git2/branch.h | 12 +++++++++ src/branch.c | 57 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/include/git2/branch.h b/include/git2/branch.h index 34354f4e5..88fe723a0 100644 --- a/include/git2/branch.h +++ b/include/git2/branch.h @@ -245,6 +245,18 @@ GIT_EXTERN(int) git_branch_upstream_name( GIT_EXTERN(int) git_branch_is_head( const git_reference *branch); +/** + * Determine if the current branch is checked out in any linked + * repository. + * + * @param branch Reference to the branch. + * + * @return 1 if branch is checked out, 0 if it isn't, + * error code otherwise. + */ +GIT_EXTERN(int) git_branch_is_checked_out( + const git_reference *branch); + /** * Return the name of remote that the remote tracking branch belongs to. * diff --git a/src/branch.c b/src/branch.c index 7ddcb3da7..e48cb1f68 100644 --- a/src/branch.c +++ b/src/branch.c @@ -13,6 +13,7 @@ #include "refs.h" #include "remote.h" #include "annotated_commit.h" +#include "worktree.h" #include "git2/branch.h" @@ -126,6 +127,62 @@ int git_branch_create_from_annotated( repository, branch_name, commit->commit, commit->description, force); } +int git_branch_is_checked_out( + const git_reference *branch) +{ + git_buf path = GIT_BUF_INIT, buf = GIT_BUF_INIT; + git_strarray worktrees; + git_reference *ref = NULL; + git_repository *repo; + const char *worktree; + int found = false; + size_t i; + + assert(branch && git_reference_is_branch(branch)); + + repo = git_reference_owner(branch); + + if (git_worktree_list(&worktrees, repo) < 0) + return -1; + + for (i = 0; i < worktrees.count; i++) { + worktree = worktrees.strings[i]; + + if (git_repository_head_for_worktree(&ref, repo, worktree) < 0) + continue; + + if (git__strcmp(ref->name, branch->name) == 0) { + found = true; + git_reference_free(ref); + break; + } + + git_reference_free(ref); + } + git_strarray_free(&worktrees); + + if (found) + return found; + + /* Check HEAD of parent */ + if (git_buf_joinpath(&path, repo->commondir, GIT_HEAD_FILE) < 0) + goto out; + if (git_futils_readbuffer(&buf, path.ptr) < 0) + goto out; + if (git__prefixcmp(buf.ptr, "ref: ") == 0) + git_buf_consume(&buf, buf.ptr + strlen("ref: ")); + git_buf_rtrim(&buf); + + found = git__strcmp(buf.ptr, branch->name) == 0; + +out: + git_buf_free(&buf); + git_buf_free(&path); + + return found; +} + + int git_branch_delete(git_reference *branch) { int is_head; From 143e539fd0e9b83c6a3a369d5baf508ccb51697b Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 6 Nov 2015 12:33:59 +0100 Subject: [PATCH 098/366] branch: restrict branch deletion for worktrees Restrict the ability to delete branches that are checked out in any linked repository. --- src/branch.c | 6 ++++++ tests/worktree/refs.c | 27 +++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/branch.c b/src/branch.c index e48cb1f68..7d5e9cb7f 100644 --- a/src/branch.c +++ b/src/branch.c @@ -206,6 +206,12 @@ int git_branch_delete(git_reference *branch) return -1; } + if (git_reference_is_branch(branch) && git_branch_is_checked_out(branch)) { + giterr_set(GITERR_REFERENCE, "Cannot delete branch '%s' as it is " + "the current HEAD of a linked repository.", git_reference_name(branch)); + return -1; + } + if (git_buf_join(&config_section, '.', "branch", git_reference_name(branch) + strlen(GIT_REFS_HEADS_DIR)) < 0) goto on_error; diff --git a/tests/worktree/refs.c b/tests/worktree/refs.c index e08e55372..38f612713 100644 --- a/tests/worktree/refs.c +++ b/tests/worktree/refs.c @@ -1,4 +1,5 @@ #include "clar_libgit2.h" +#include "worktree.h" #include "worktree_helpers.h" #define COMMON_REPO "testrepo" @@ -66,3 +67,29 @@ void test_worktree_refs__read_head(void) git_reference_free(head); } + +void test_worktree_refs__delete_fails_for_checked_out_branch(void) +{ + git_reference *branch; + + cl_git_pass(git_branch_lookup(&branch, fixture.repo, + "testrepo-worktree", GIT_BRANCH_LOCAL)); + cl_git_fail(git_branch_delete(branch)); + + git_reference_free(branch); +} + +void test_worktree_refs__delete_succeeds_after_pruning_worktree(void) +{ + git_reference *branch; + git_worktree *worktree; + + cl_git_pass(git_worktree_lookup(&worktree, fixture.repo, fixture.worktreename)); + cl_git_pass(git_worktree_prune(worktree, GIT_WORKTREE_PRUNE_VALID)); + git_worktree_free(worktree); + + cl_git_pass(git_branch_lookup(&branch, fixture.repo, + "testrepo-worktree", GIT_BRANCH_LOCAL)); + cl_git_pass(git_branch_delete(branch)); + git_reference_free(branch); +} From 384518d09dc16b8a7dae22069e0c612e4b65c5e8 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Tue, 27 Oct 2015 14:17:52 +0100 Subject: [PATCH 099/366] repository: restrict checking out checked out branches If a branch is already checked out in a working tree we are not allowed to check out that branch in another repository. Introduce this restriction when setting a repository's HEAD. --- src/repository.c | 6 ++++++ tests/worktree/refs.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/src/repository.c b/src/repository.c index 445005e96..8753636cb 100644 --- a/src/repository.c +++ b/src/repository.c @@ -2529,6 +2529,12 @@ int git_repository_set_head( if (error < 0 && error != GIT_ENOTFOUND) goto cleanup; + if (ref && current->type == GIT_REF_SYMBOLIC && git__strcmp(current->target.symbolic, ref->name) && + git_reference_is_branch(ref) && git_branch_is_checked_out(ref)) { + error = -1; + goto cleanup; + } + if (!error) { if (git_reference_is_branch(ref)) { error = git_reference_symbolic_create(&new_head, repo, GIT_HEAD_FILE, diff --git a/tests/worktree/refs.c b/tests/worktree/refs.c index 38f612713..ccac8be29 100644 --- a/tests/worktree/refs.c +++ b/tests/worktree/refs.c @@ -68,6 +68,41 @@ void test_worktree_refs__read_head(void) git_reference_free(head); } +void test_worktree_refs__set_head_fails_when_worktree_wants_linked_repos_HEAD(void) +{ + git_reference *head; + + cl_git_pass(git_repository_head(&head, fixture.repo)); + cl_git_fail(git_repository_set_head(fixture.worktree, git_reference_name(head))); + + git_reference_free(head); +} + +void test_worktree_refs__set_head_fails_when_main_repo_wants_worktree_head(void) +{ + git_reference *head; + + cl_git_pass(git_repository_head(&head, fixture.worktree)); + cl_git_fail(git_repository_set_head(fixture.repo, git_reference_name(head))); + + git_reference_free(head); +} + +void test_worktree_refs__set_head_works_for_current_HEAD(void) +{ + git_reference *head; + + cl_git_pass(git_repository_head(&head, fixture.repo)); + cl_git_pass(git_repository_set_head(fixture.repo, git_reference_name(head))); + + git_reference_free(head); +} + +void test_worktree_refs__set_head_fails_when_already_checked_out(void) +{ + cl_git_fail(git_repository_set_head(fixture.repo, "refs/heads/testrepo-worktree")); +} + void test_worktree_refs__delete_fails_for_checked_out_branch(void) { git_reference *branch; From 84f56cb05afe7a60501f310ba1329bb98ef8756d Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 4 Nov 2016 11:59:52 +0100 Subject: [PATCH 100/366] repository: rename `path_repository` and `path_gitlink` The `path_repository` variable is actually confusing to think about, as it is not always clear what the repository actually is. It may either be the path to the folder containing worktree and .git directory, the path to .git itself, a worktree or something entirely different. Actually, the intent of the variable is to hold the path to the gitdir, which is either the .git directory or the bare repository. Rename the variable to `gitdir` to avoid confusion. While at it, also rename `path_gitlink` to `gitlink` to improve consistency. --- src/cherrypick.c | 4 ++-- src/fetchhead.c | 4 ++-- src/merge.c | 10 ++++---- src/rebase.c | 6 ++--- src/refdb_fs.c | 6 ++--- src/repository.c | 48 +++++++++++++++++++-------------------- src/repository.h | 4 ++-- src/revert.c | 4 ++-- tests/worktree/merge.c | 2 +- tests/worktree/worktree.c | 12 +++++----- 10 files changed, 50 insertions(+), 50 deletions(-) diff --git a/src/cherrypick.c b/src/cherrypick.c index ab067339e..d8b6858ae 100644 --- a/src/cherrypick.c +++ b/src/cherrypick.c @@ -28,7 +28,7 @@ static int write_cherrypick_head( git_buf file_path = GIT_BUF_INIT; int error = 0; - if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_CHERRYPICK_HEAD_FILE)) >= 0 && + if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_CHERRYPICK_HEAD_FILE)) >= 0 && (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_CHERRYPICK_FILE_MODE)) >= 0 && (error = git_filebuf_printf(&file, "%s\n", commit_oidstr)) >= 0) error = git_filebuf_commit(&file); @@ -49,7 +49,7 @@ static int write_merge_msg( git_buf file_path = GIT_BUF_INIT; int error = 0; - if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_MERGE_MSG_FILE)) < 0 || + if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_MERGE_MSG_FILE)) < 0 || (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_CHERRYPICK_FILE_MODE)) < 0 || (error = git_filebuf_printf(&file, "%s", commit_msg)) < 0) goto cleanup; diff --git a/src/fetchhead.c b/src/fetchhead.c index 0d9ab2c25..6e6f3eb5e 100644 --- a/src/fetchhead.c +++ b/src/fetchhead.c @@ -115,7 +115,7 @@ int git_fetchhead_write(git_repository *repo, git_vector *fetchhead_refs) assert(repo && fetchhead_refs); - if (git_buf_joinpath(&path, repo->path_repository, GIT_FETCH_HEAD_FILE) < 0) + if (git_buf_joinpath(&path, repo->gitdir, GIT_FETCH_HEAD_FILE) < 0) return -1; if (git_filebuf_open(&file, path.ptr, GIT_FILEBUF_FORCE, GIT_REFS_FILE_MODE) < 0) { @@ -249,7 +249,7 @@ int git_repository_fetchhead_foreach(git_repository *repo, assert(repo && cb); - if (git_buf_joinpath(&path, repo->path_repository, GIT_FETCH_HEAD_FILE) < 0) + if (git_buf_joinpath(&path, repo->gitdir, GIT_FETCH_HEAD_FILE) < 0) return -1; if ((error = git_futils_readbuffer(&file, git_buf_cstr(&path))) < 0) diff --git a/src/merge.c b/src/merge.c index eceadf08a..857d51311 100644 --- a/src/merge.c +++ b/src/merge.c @@ -562,7 +562,7 @@ int git_repository_mergehead_foreach( assert(repo && cb); - if ((error = git_buf_joinpath(&merge_head_path, repo->path_repository, + if ((error = git_buf_joinpath(&merge_head_path, repo->gitdir, GIT_MERGE_HEAD_FILE)) < 0) return error; @@ -2277,7 +2277,7 @@ static int write_merge_head( assert(repo && heads); - if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_MERGE_HEAD_FILE)) < 0 || + if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_MERGE_HEAD_FILE)) < 0 || (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_MERGE_FILE_MODE)) < 0) goto cleanup; @@ -2305,7 +2305,7 @@ static int write_merge_mode(git_repository *repo) assert(repo); - if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_MERGE_MODE_FILE)) < 0 || + if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_MERGE_MODE_FILE)) < 0 || (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_MERGE_FILE_MODE)) < 0) goto cleanup; @@ -2536,7 +2536,7 @@ static int write_merge_msg( for (i = 0; i < heads_len; i++) entries[i].merge_head = heads[i]; - if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_MERGE_MSG_FILE)) < 0 || + if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_MERGE_MSG_FILE)) < 0 || (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_MERGE_FILE_MODE)) < 0 || (error = git_filebuf_write(&file, "Merge ", 6)) < 0) goto cleanup; @@ -2914,7 +2914,7 @@ int git_merge__append_conflicts_to_merge_msg( if (!git_index_has_conflicts(index)) return 0; - if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_MERGE_MSG_FILE)) < 0 || + if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_MERGE_MSG_FILE)) < 0 || (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_APPEND, GIT_MERGE_FILE_MODE)) < 0) goto cleanup; diff --git a/src/rebase.c b/src/rebase.c index b2024a439..09941a2a2 100644 --- a/src/rebase.c +++ b/src/rebase.c @@ -92,7 +92,7 @@ static int rebase_state_type( git_buf path = GIT_BUF_INIT; git_rebase_type_t type = GIT_REBASE_TYPE_NONE; - if (git_buf_joinpath(&path, repo->path_repository, REBASE_APPLY_DIR) < 0) + if (git_buf_joinpath(&path, repo->gitdir, REBASE_APPLY_DIR) < 0) return -1; if (git_path_isdir(git_buf_cstr(&path))) { @@ -101,7 +101,7 @@ static int rebase_state_type( } git_buf_clear(&path); - if (git_buf_joinpath(&path, repo->path_repository, REBASE_MERGE_DIR) < 0) + if (git_buf_joinpath(&path, repo->gitdir, REBASE_MERGE_DIR) < 0) return -1; if (git_path_isdir(git_buf_cstr(&path))) { @@ -624,7 +624,7 @@ static int rebase_init_merge( GIT_UNUSED(upstream); - if ((error = git_buf_joinpath(&state_path, repo->path_repository, REBASE_MERGE_DIR)) < 0) + if ((error = git_buf_joinpath(&state_path, repo->gitdir, REBASE_MERGE_DIR)) < 0) goto done; rebase->state_path = git_buf_detach(&state_path); diff --git a/src/refdb_fs.c b/src/refdb_fs.c index 91183cd71..3d690630e 100644 --- a/src/refdb_fs.c +++ b/src/refdb_fs.c @@ -1435,13 +1435,13 @@ static int setup_namespace(git_buf *gitpath, git_repository *repo) char *parts, *start, *end; /* Not all repositories have a gitpath */ - if (repo->path_repository == NULL) + if (repo->gitdir == NULL) return 0; if (repo->commondir == NULL) return 0; /* Load the path to the repo first */ - git_buf_puts(gitpath, repo->path_repository); + git_buf_puts(gitpath, repo->gitdir); /* if the repo is not namespaced, nothing else to do */ if (repo->namespace == NULL) @@ -1877,7 +1877,7 @@ static int refdb_reflog_fs__rename(git_refdb_backend *_backend, const char *old_ &normalized, new_name, GIT_REF_FORMAT_ALLOW_ONELEVEL)) < 0) return error; - if (git_buf_joinpath(&temp_path, repo->path_repository, GIT_REFLOG_DIR) < 0) + if (git_buf_joinpath(&temp_path, repo->gitdir, GIT_REFLOG_DIR) < 0) return -1; if (git_buf_joinpath(&old_path, git_buf_cstr(&temp_path), old_name) < 0) diff --git a/src/repository.c b/src/repository.c index 8753636cb..55724845f 100644 --- a/src/repository.c +++ b/src/repository.c @@ -165,8 +165,8 @@ void git_repository_free(git_repository *repo) git_buf_free(git_array_get(repo->reserved_names, i)); git_array_clear(repo->reserved_names); - git__free(repo->path_gitlink); - git__free(repo->path_repository); + git__free(repo->gitlink); + git__free(repo->gitdir); git__free(repo->commondir); git__free(repo->workdir); git__free(repo->namespace); @@ -288,7 +288,7 @@ static int load_workdir(git_repository *repo, git_config *config, git_buf *paren if (ce && ce->value) { if ((error = git_path_prettify_dir( - &worktree, ce->value, repo->path_repository)) < 0) + &worktree, ce->value, repo->gitdir)) < 0) goto cleanup; repo->workdir = git_buf_detach(&worktree); @@ -296,7 +296,7 @@ static int load_workdir(git_repository *repo, git_config *config, git_buf *paren else if (parent_path && git_path_isdir(parent_path->ptr)) repo->workdir = git_buf_detach(parent_path); else { - if (git_path_dirname_r(&worktree, repo->path_repository) < 0 || + if (git_path_dirname_r(&worktree, repo->gitdir) < 0 || git_path_to_dir(&worktree) < 0) { error = -1; goto cleanup; @@ -553,8 +553,8 @@ int git_repository_open_bare( repo = repository_alloc(); GITERR_CHECK_ALLOC(repo); - repo->path_repository = git_buf_detach(&path); - GITERR_CHECK_ALLOC(repo->path_repository); + repo->gitdir = git_buf_detach(&path); + GITERR_CHECK_ALLOC(repo->gitdir); repo->commondir = git_buf_detach(&common_path); GITERR_CHECK_ALLOC(repo->commondir); @@ -763,19 +763,19 @@ int git_repository_open_ext( repo = repository_alloc(); GITERR_CHECK_ALLOC(repo); - repo->path_repository = git_buf_detach(&path); - GITERR_CHECK_ALLOC(repo->path_repository); + repo->gitdir = git_buf_detach(&path); + GITERR_CHECK_ALLOC(repo->gitdir); if (link_path.size) { - repo->path_gitlink = git_buf_detach(&link_path); - GITERR_CHECK_ALLOC(repo->path_gitlink); + repo->gitlink = git_buf_detach(&link_path); + GITERR_CHECK_ALLOC(repo->gitlink); } if (common_path.size) { repo->commondir = git_buf_detach(&common_path); GITERR_CHECK_ALLOC(repo->commondir); } - if (repo->path_gitlink && repo->commondir && strcmp(repo->path_gitlink, repo->commondir)) + if (repo->gitlink && repo->commondir && strcmp(repo->gitlink, repo->commondir)) repo->is_worktree = 1; /* @@ -1114,7 +1114,7 @@ int git_repository_index__weakptr(git_index **out, git_repository *repo) git_buf index_path = GIT_BUF_INIT; git_index *index; - if ((error = git_buf_joinpath(&index_path, repo->path_repository, GIT_INDEX_FILE)) < 0) + if ((error = git_buf_joinpath(&index_path, repo->gitdir, GIT_INDEX_FILE)) < 0) return error; error = git_index_open(&index, index_path.ptr); @@ -1230,13 +1230,13 @@ bool git_repository__reserved_names( prefixcmp = (error || ignorecase) ? git__prefixcmp_icase : git__prefixcmp; - if (repo->path_gitlink && - reserved_names_add8dot3(repo, repo->path_gitlink) < 0) + if (repo->gitlink && + reserved_names_add8dot3(repo, repo->gitlink) < 0) goto on_error; - if (repo->path_repository && - prefixcmp(repo->path_repository, repo->workdir) == 0 && - reserved_names_add8dot3(repo, repo->path_repository) < 0) + if (repo->gitdir && + prefixcmp(repo->gitdir, repo->workdir) == 0 && + reserved_names_add8dot3(repo, repo->gitdir) < 0) goto on_error; } } @@ -2237,7 +2237,7 @@ int git_repository_item_path(git_buf *out, git_repository *repo, git_repository_ const char *git_repository_path(git_repository *repo) { assert(repo); - return repo->path_repository; + return repo->gitdir; } const char *git_repository_workdir(git_repository *repo) @@ -2366,7 +2366,7 @@ int git_repository__set_orig_head(git_repository *repo, const git_oid *orig_head git_oid_fmt(orig_head_str, orig_head); - if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_ORIG_HEAD_FILE)) == 0 && + if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_ORIG_HEAD_FILE)) == 0 && (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_MERGE_FILE_MODE)) == 0 && (error = git_filebuf_printf(&file, "%.*s\n", GIT_OID_HEXSZ, orig_head_str)) == 0) error = git_filebuf_commit(&file); @@ -2387,7 +2387,7 @@ int git_repository_message(git_buf *out, git_repository *repo) git_buf_sanitize(out); - if (git_buf_joinpath(&path, repo->path_repository, GIT_MERGE_MSG_FILE) < 0) + if (git_buf_joinpath(&path, repo->gitdir, GIT_MERGE_MSG_FILE) < 0) return -1; if ((error = p_stat(git_buf_cstr(&path), &st)) < 0) { @@ -2408,7 +2408,7 @@ int git_repository_message_remove(git_repository *repo) git_buf path = GIT_BUF_INIT; int error; - if (git_buf_joinpath(&path, repo->path_repository, GIT_MERGE_MSG_FILE) < 0) + if (git_buf_joinpath(&path, repo->gitdir, GIT_MERGE_MSG_FILE) < 0) return -1; error = p_unlink(git_buf_cstr(&path)); @@ -2650,7 +2650,7 @@ int git_repository_state(git_repository *repo) assert(repo); - if (git_buf_puts(&repo_path, repo->path_repository) < 0) + if (git_buf_puts(&repo_path, repo->gitdir) < 0) return -1; if (git_path_contains_file(&repo_path, GIT_REBASE_MERGE_INTERACTIVE_FILE)) @@ -2692,7 +2692,7 @@ int git_repository__cleanup_files( for (error = 0, i = 0; !error && i < files_len; ++i) { const char *path; - if (git_buf_joinpath(&buf, repo->path_repository, files[i]) < 0) + if (git_buf_joinpath(&buf, repo->gitdir, files[i]) < 0) return -1; path = git_buf_cstr(&buf); @@ -2736,7 +2736,7 @@ int git_repository_is_shallow(git_repository *repo) struct stat st; int error; - if ((error = git_buf_joinpath(&path, repo->path_repository, "shallow")) < 0) + if ((error = git_buf_joinpath(&path, repo->gitdir, "shallow")) < 0) return error; error = git_path_lstat(path.ptr, &st); diff --git a/src/repository.h b/src/repository.h index 74e15e146..c328ecd21 100644 --- a/src/repository.h +++ b/src/repository.h @@ -126,8 +126,8 @@ struct git_repository { git_attr_cache *attrcache; git_diff_driver_registry *diff_drivers; - char *path_repository; - char *path_gitlink; + char *gitlink; + char *gitdir; char *commondir; char *workdir; char *namespace; diff --git a/src/revert.c b/src/revert.c index b255245bf..747938fb3 100644 --- a/src/revert.c +++ b/src/revert.c @@ -27,7 +27,7 @@ static int write_revert_head( git_buf file_path = GIT_BUF_INIT; int error = 0; - if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_REVERT_HEAD_FILE)) >= 0 && + if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_REVERT_HEAD_FILE)) >= 0 && (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_REVERT_FILE_MODE)) >= 0 && (error = git_filebuf_printf(&file, "%s\n", commit_oidstr)) >= 0) error = git_filebuf_commit(&file); @@ -49,7 +49,7 @@ static int write_merge_msg( git_buf file_path = GIT_BUF_INIT; int error = 0; - if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_MERGE_MSG_FILE)) < 0 || + if ((error = git_buf_joinpath(&file_path, repo->gitdir, GIT_MERGE_MSG_FILE)) < 0 || (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_REVERT_FILE_MODE)) < 0 || (error = git_filebuf_printf(&file, "Revert \"%s\"\n\nThis reverts commit %s.\n", commit_msgline, commit_oidstr)) < 0) diff --git a/tests/worktree/merge.c b/tests/worktree/merge.c index 8221e4fc1..36cc2a6c1 100644 --- a/tests/worktree/merge.c +++ b/tests/worktree/merge.c @@ -72,7 +72,7 @@ void test_worktree_merge__merge_setup(void) for (i = 0; i < ARRAY_SIZE(merge_files); i++) { git_buf_clear(&path); cl_git_pass(git_buf_printf(&path, "%s/%s", - fixture.worktree->path_repository, merge_files[i])); + fixture.worktree->gitdir, merge_files[i])); cl_assert(git_path_exists(path.ptr)); } diff --git a/tests/worktree/worktree.c b/tests/worktree/worktree.c index 756cf387b..81d592951 100644 --- a/tests/worktree/worktree.c +++ b/tests/worktree/worktree.c @@ -117,8 +117,8 @@ void test_worktree_worktree__lookup(void) git_buf_printf(&gitdir_path, "%s/worktrees/%s", fixture.repo->commondir, "testrepo-worktree"); cl_assert_equal_s(wt->gitdir_path, gitdir_path.ptr); - cl_assert_equal_s(wt->parent_path, fixture.repo->path_repository); - cl_assert_equal_s(wt->gitlink_path, fixture.worktree->path_gitlink); + cl_assert_equal_s(wt->parent_path, fixture.repo->gitdir); + cl_assert_equal_s(wt->gitlink_path, fixture.worktree->gitlink); cl_assert_equal_s(wt->commondir_path, fixture.repo->commondir); git_buf_free(&gitdir_path); @@ -196,7 +196,7 @@ void test_worktree_worktree__open_invalid_parent(void) cl_git_pass(git_buf_sets(&buf, "/path/to/nonexistent/gitdir")); cl_git_pass(git_futils_writebuffer(&buf, - fixture.worktree->path_gitlink, O_RDWR, 0644)); + fixture.worktree->gitlink, O_RDWR, 0644)); cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree")); cl_git_fail(git_repository_open_from_worktree(&repo, wt)); @@ -254,7 +254,7 @@ void test_worktree_worktree__init_existing_worktree(void) cl_git_fail(git_worktree_add(&wt, fixture.repo, "testrepo-worktree", path.ptr)); cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree")); - cl_assert_equal_s(wt->gitlink_path, fixture.worktree->path_gitlink); + cl_assert_equal_s(wt->gitlink_path, fixture.worktree->gitlink); git_buf_free(&path); git_worktree_free(wt); @@ -271,7 +271,7 @@ void test_worktree_worktree__init_existing_path(void) * the init call */ for (i = 0; i < ARRAY_SIZE(wtfiles); i++) { cl_git_pass(git_buf_joinpath(&path, - fixture.worktree->path_repository, wtfiles[i])); + fixture.worktree->gitdir, wtfiles[i])); cl_git_pass(p_unlink(path.ptr)); } @@ -281,7 +281,7 @@ void test_worktree_worktree__init_existing_path(void) /* Verify files have not been re-created */ for (i = 0; i < ARRAY_SIZE(wtfiles); i++) { cl_git_pass(git_buf_joinpath(&path, - fixture.worktree->path_repository, wtfiles[i])); + fixture.worktree->gitdir, wtfiles[i])); cl_assert(!git_path_exists(path.ptr)); } From 39abd3adaa62f287f5cda0a63c7cfca647283e9c Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 4 Nov 2016 13:39:54 +0100 Subject: [PATCH 101/366] worktree: compute workdir for worktrees opened via their gitdir When opening a worktree via the gitdir of its parent repository we fail to correctly set up the worktree's working directory. The problem here is two-fold: we first fail to see that the gitdir actually is a gitdir of a working tree and then subsequently fail to determine the working tree location from the gitdir. The first problem of not noticing a gitdir belongs to a worktree can be solved by checking for the existence of a `gitdir` file in the gitdir. This file points back to the gitlink file located in the working tree's working directory. As this file only exists for worktrees, it should be sufficient indication of the gitdir belonging to a worktree. The second problem, that is determining the location of the worktree's working directory, can then be solved by reading the `gitdir` file in the working directory's gitdir. When we now resolve relative paths and strip the final `.git` component, we have the actual worktree's working directory location. --- src/repository.c | 36 ++++++++++++++++++++++++++++++++---- src/worktree.c | 6 +++--- src/worktree.h | 2 ++ tests/worktree/open.c | 33 ++++++++++++++++++++++++++++----- tests/worktree/worktree.c | 1 + 5 files changed, 66 insertions(+), 12 deletions(-) diff --git a/src/repository.c b/src/repository.c index 55724845f..4b937be20 100644 --- a/src/repository.c +++ b/src/repository.c @@ -61,6 +61,7 @@ static const struct { static int check_repositoryformatversion(git_config *config); #define GIT_COMMONDIR_FILE "commondir" +#define GIT_GITDIR_FILE "gitdir" #define GIT_FILE_CONTENT_PREFIX "gitdir:" @@ -275,9 +276,10 @@ static int load_config_data(git_repository *repo, const git_config *config) static int load_workdir(git_repository *repo, git_config *config, git_buf *parent_path) { - int error; + int error; git_config_entry *ce; - git_buf worktree = GIT_BUF_INIT; + git_buf worktree = GIT_BUF_INIT; + git_buf path = GIT_BUF_INIT; if (repo->is_bare) return 0; @@ -286,7 +288,24 @@ static int load_workdir(git_repository *repo, git_config *config, git_buf *paren &ce, config, "core.worktree", false)) < 0) return error; - if (ce && ce->value) { + if (repo->is_worktree) { + char *gitlink = git_worktree__read_link(repo->gitdir, GIT_GITDIR_FILE); + if (!gitlink) { + error = -1; + goto cleanup; + } + + git_buf_attach(&worktree, gitlink, 0); + + if ((git_path_dirname_r(&worktree, worktree.ptr)) < 0 || + git_path_to_dir(&worktree) < 0) { + error = -1; + goto cleanup; + } + + repo->workdir = git_buf_detach(&worktree); + } + else if (ce && ce->value) { if ((error = git_path_prettify_dir( &worktree, ce->value, repo->gitdir)) < 0) goto cleanup; @@ -307,6 +326,7 @@ static int load_workdir(git_repository *repo, git_config *config, git_buf *paren GITERR_CHECK_ALLOC(repo->workdir); cleanup: + git_buf_free(&path); git_config_entry_free(ce); return error; } @@ -465,6 +485,9 @@ static int find_repo( git_path_to_dir(&path); git_buf_set(repo_path, path.ptr, path.size); + if (link_path) + git_buf_attach(link_path, + git_worktree__read_link(path.ptr, GIT_GITDIR_FILE), 0); if (common_path) git_buf_swap(&common_link, common_path); @@ -775,7 +798,11 @@ int git_repository_open_ext( GITERR_CHECK_ALLOC(repo->commondir); } - if (repo->gitlink && repo->commondir && strcmp(repo->gitlink, repo->commondir)) + if ((error = git_buf_joinpath(&path, repo->gitdir, "gitdir")) < 0) + goto cleanup; + /* A 'gitdir' file inside a git directory is currently + * only used when the repository is a working tree. */ + if (git_path_exists(path.ptr)) repo->is_worktree = 1; /* @@ -801,6 +828,7 @@ int git_repository_open_ext( } cleanup: + git_buf_free(&path); git_buf_free(&parent); git_config_free(config); diff --git a/src/worktree.c b/src/worktree.c index 95a2757fe..a3fe07a23 100644 --- a/src/worktree.c +++ b/src/worktree.c @@ -61,7 +61,7 @@ exit: return error; } -static char *read_link(const char *base, const char *file) +char *git_worktree__read_link(const char *base, const char *file) { git_buf path = GIT_BUF_INIT, buf = GIT_BUF_INIT; @@ -136,8 +136,8 @@ int git_worktree_lookup(git_worktree **out, git_repository *repo, const char *na } if ((wt->name = git__strdup(name)) == NULL - || (wt->commondir_path = read_link(path.ptr, "commondir")) == NULL - || (wt->gitlink_path = read_link(path.ptr, "gitdir")) == NULL + || (wt->commondir_path = git_worktree__read_link(path.ptr, "commondir")) == NULL + || (wt->gitlink_path = git_worktree__read_link(path.ptr, "gitdir")) == NULL || (wt->parent_path = git__strdup(git_repository_path(repo))) == NULL) { error = -1; goto out; diff --git a/src/worktree.h b/src/worktree.h index 0e1a88d98..b8e527968 100644 --- a/src/worktree.h +++ b/src/worktree.h @@ -30,4 +30,6 @@ struct git_worktree { int locked:1; }; +char *git_worktree__read_link(const char *base, const char *file); + #endif diff --git a/tests/worktree/open.c b/tests/worktree/open.c index 54a8af4a3..f5b668177 100644 --- a/tests/worktree/open.c +++ b/tests/worktree/open.c @@ -5,10 +5,13 @@ #define WORKTREE_PARENT "submodules-worktree-parent" #define WORKTREE_CHILD "submodules-worktree-child" +#define COMMON_REPO "testrepo" +#define WORKTREE_REPO "testrepo-worktree" + void test_worktree_open__repository(void) { worktree_fixture fixture = - WORKTREE_FIXTURE_INIT("testrepo", "testrepo-worktree"); + WORKTREE_FIXTURE_INIT(COMMON_REPO, WORKTREE_REPO); setup_fixture_worktree(&fixture); cl_assert(git_repository_path(fixture.worktree) != NULL); @@ -20,18 +23,38 @@ void test_worktree_open__repository(void) cleanup_fixture_worktree(&fixture); } +void test_worktree_open__open_discovered_worktree(void) +{ + worktree_fixture fixture = + WORKTREE_FIXTURE_INIT(COMMON_REPO, WORKTREE_REPO); + git_buf path = GIT_BUF_INIT; + git_repository *repo; + + setup_fixture_worktree(&fixture); + + cl_git_pass(git_repository_discover(&path, + git_repository_workdir(fixture.worktree), false, NULL)); + cl_git_pass(git_repository_open(&repo, path.ptr)); + cl_assert_equal_s(git_repository_workdir(fixture.worktree), + git_repository_workdir(repo)); + + git_buf_free(&path); + git_repository_free(repo); + cleanup_fixture_worktree(&fixture); +} + void test_worktree_open__repository_with_nonexistent_parent(void) { git_repository *repo; - cl_fixture_sandbox("testrepo-worktree"); - cl_git_pass(p_chdir("testrepo-worktree")); + cl_fixture_sandbox(WORKTREE_REPO); + cl_git_pass(p_chdir(WORKTREE_REPO)); cl_git_pass(cl_rename(".gitted", ".git")); cl_git_pass(p_chdir("..")); - cl_git_fail(git_repository_open(&repo, "testrepo-worktree")); + cl_git_fail(git_repository_open(&repo, WORKTREE_REPO)); - cl_fixture_cleanup("testrepo-worktree"); + cl_fixture_cleanup(WORKTREE_REPO); } void test_worktree_open__submodule_worktree_parent(void) diff --git a/tests/worktree/worktree.c b/tests/worktree/worktree.c index 81d592951..959c56520 100644 --- a/tests/worktree/worktree.c +++ b/tests/worktree/worktree.c @@ -217,6 +217,7 @@ void test_worktree_worktree__init(void) /* Open and verify created repo */ cl_git_pass(git_repository_open(&repo, path.ptr)); + cl_assert(git__suffixcmp(git_repository_workdir(repo), "worktree-new/") == 0); cl_git_pass(git_branch_lookup(&branch, repo, "worktree-new", GIT_BRANCH_LOCAL)); git_buf_free(&path); From 1fd6e035ddb27a0271c5cc734698835317e93249 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Mon, 7 Nov 2016 10:23:34 +0100 Subject: [PATCH 102/366] worktree: test opening discovered submodule worktrees --- tests/worktree/open.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/worktree/open.c b/tests/worktree/open.c index f5b668177..2dc445a66 100644 --- a/tests/worktree/open.c +++ b/tests/worktree/open.c @@ -92,3 +92,30 @@ void test_worktree_open__submodule_worktree_child(void) cleanup_fixture_worktree(&child_fixture); cleanup_fixture_worktree(&parent_fixture); } + +void test_worktree_open__open_discovered_submodule_worktree(void) +{ + worktree_fixture parent_fixture = + WORKTREE_FIXTURE_INIT("submodules", WORKTREE_PARENT); + worktree_fixture child_fixture = + WORKTREE_FIXTURE_INIT(NULL, WORKTREE_CHILD); + git_buf path = GIT_BUF_INIT; + git_repository *repo; + + setup_fixture_worktree(&parent_fixture); + cl_git_pass(p_rename( + "submodules/testrepo/.gitted", + "submodules/testrepo/.git")); + setup_fixture_worktree(&child_fixture); + + cl_git_pass(git_repository_discover(&path, + git_repository_workdir(child_fixture.worktree), false, NULL)); + cl_git_pass(git_repository_open(&repo, path.ptr)); + cl_assert_equal_s(git_repository_workdir(child_fixture.worktree), + git_repository_workdir(repo)); + + git_buf_free(&path); + git_repository_free(repo); + cleanup_fixture_worktree(&child_fixture); + cleanup_fixture_worktree(&parent_fixture); +} From 6f6dd17cb280d7d0f45f48fb618cc02df18b868a Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Tue, 8 Nov 2016 12:13:59 +0100 Subject: [PATCH 103/366] worktree: test creating and opening submodule worktrees --- tests/worktree/worktree.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/tests/worktree/worktree.c b/tests/worktree/worktree.c index 959c56520..f0c423599 100644 --- a/tests/worktree/worktree.c +++ b/tests/worktree/worktree.c @@ -1,5 +1,6 @@ #include "clar_libgit2.h" #include "worktree_helpers.h" +#include "submodule/submodule_helpers.h" #include "checkout.h" #include "repository.h" @@ -289,6 +290,33 @@ void test_worktree_worktree__init_existing_path(void) git_buf_free(&path); } +void test_worktree_worktree__init_submodule(void) +{ + git_repository *repo, *sm, *wt; + git_worktree *worktree; + git_buf path = GIT_BUF_INIT; + + cleanup_fixture_worktree(&fixture); + repo = setup_fixture_submod2(); + + cl_git_pass(git_buf_joinpath(&path, repo->workdir, "sm_unchanged")); + cl_git_pass(git_repository_open(&sm, path.ptr)); + cl_git_pass(git_buf_joinpath(&path, repo->workdir, "../worktree/")); + cl_git_pass(git_worktree_add(&worktree, sm, "repo-worktree", path.ptr)); + cl_git_pass(git_repository_open_from_worktree(&wt, worktree)); + + cl_assert_equal_s(path.ptr, wt->workdir); + cl_assert_equal_s(sm->commondir, wt->commondir); + + cl_git_pass(git_buf_joinpath(&path, sm->gitdir, "worktrees/repo-worktree/")); + cl_assert_equal_s(path.ptr, wt->gitdir); + + git_buf_free(&path); + git_worktree_free(worktree); + git_repository_free(sm); + git_repository_free(wt); +} + void test_worktree_worktree__validate(void) { git_worktree *wt; From 3f3a4ce7bcd9862ef1eb87dfc5871e4012159244 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 9 Nov 2016 14:18:22 +0100 Subject: [PATCH 104/366] worktree: test opening worktree via gitlink, gitdir and worktree --- tests/worktree/open.c | 81 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 77 insertions(+), 4 deletions(-) diff --git a/tests/worktree/open.c b/tests/worktree/open.c index 2dc445a66..bdc8bcf9d 100644 --- a/tests/worktree/open.c +++ b/tests/worktree/open.c @@ -8,18 +8,91 @@ #define COMMON_REPO "testrepo" #define WORKTREE_REPO "testrepo-worktree" +static void assert_worktree_valid(git_repository *wt, const char *parentdir, const char *wtdir) +{ + git_buf path = GIT_BUF_INIT; + + cl_assert(wt->is_worktree); + + cl_git_pass(git_buf_joinpath(&path, clar_sandbox_path(), wtdir)); + cl_git_pass(git_path_prettify(&path, path.ptr, NULL)); + cl_git_pass(git_path_to_dir(&path)); + cl_assert_equal_s(wt->workdir, path.ptr); + + cl_git_pass(git_buf_joinpath(&path, path.ptr, ".git")); + cl_git_pass(git_path_prettify(&path, path.ptr, NULL)); + cl_assert_equal_s(wt->gitlink, path.ptr); + + cl_git_pass(git_buf_joinpath(&path, clar_sandbox_path(), parentdir)); + cl_git_pass(git_buf_joinpath(&path, path.ptr, ".git")); + cl_git_pass(git_buf_joinpath(&path, path.ptr, "worktrees")); + cl_git_pass(git_buf_joinpath(&path, path.ptr, wtdir)); + cl_git_pass(git_path_prettify(&path, path.ptr, NULL)); + cl_git_pass(git_path_to_dir(&path)); + cl_assert_equal_s(wt->gitdir, path.ptr); + + git_buf_free(&path); +} + void test_worktree_open__repository(void) { worktree_fixture fixture = WORKTREE_FIXTURE_INIT(COMMON_REPO, WORKTREE_REPO); setup_fixture_worktree(&fixture); - cl_assert(git_repository_path(fixture.worktree) != NULL); - cl_assert(git_repository_workdir(fixture.worktree) != NULL); + assert_worktree_valid(fixture.worktree, COMMON_REPO, WORKTREE_REPO); - cl_assert(!fixture.repo->is_worktree); - cl_assert(fixture.worktree->is_worktree); + cleanup_fixture_worktree(&fixture); +} +void test_worktree_open__repository_through_workdir(void) +{ + worktree_fixture fixture = + WORKTREE_FIXTURE_INIT(COMMON_REPO, WORKTREE_REPO); + git_repository *wt; + + setup_fixture_worktree(&fixture); + + cl_git_pass(git_repository_open(&wt, WORKTREE_REPO)); + assert_worktree_valid(wt, COMMON_REPO, WORKTREE_REPO); + + git_repository_free(wt); + cleanup_fixture_worktree(&fixture); +} + +void test_worktree_open__repository_through_gitlink(void) +{ + worktree_fixture fixture = + WORKTREE_FIXTURE_INIT(COMMON_REPO, WORKTREE_REPO); + git_repository *wt; + + setup_fixture_worktree(&fixture); + + cl_git_pass(git_repository_open(&wt, WORKTREE_REPO "/.git")); + assert_worktree_valid(wt, COMMON_REPO, WORKTREE_REPO); + + git_repository_free(wt); + cleanup_fixture_worktree(&fixture); +} + +void test_worktree_open__repository_through_gitdir(void) +{ + worktree_fixture fixture = + WORKTREE_FIXTURE_INIT(COMMON_REPO, WORKTREE_REPO); + git_buf gitdir_path = GIT_BUF_INIT; + git_repository *wt; + + setup_fixture_worktree(&fixture); + + cl_git_pass(git_buf_joinpath(&gitdir_path, COMMON_REPO, ".git")); + cl_git_pass(git_buf_joinpath(&gitdir_path, gitdir_path.ptr, "worktrees")); + cl_git_pass(git_buf_joinpath(&gitdir_path, gitdir_path.ptr, "testrepo-worktree")); + + cl_git_pass(git_repository_open(&wt, gitdir_path.ptr)); + assert_worktree_valid(wt, COMMON_REPO, WORKTREE_REPO); + + git_buf_free(&gitdir_path); + git_repository_free(wt); cleanup_fixture_worktree(&fixture); } From 1ba242c9ab0eb323abed1b3bbc770aeb3367d855 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 3 Feb 2017 13:52:23 +0100 Subject: [PATCH 105/366] worktree: extract git_worktree_is_prunable --- include/git2/worktree.h | 18 ++++++++++++++++++ src/worktree.c | 24 +++++++++++++++++------- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/include/git2/worktree.h b/include/git2/worktree.h index ec869fb59..cad1284fa 100644 --- a/include/git2/worktree.h +++ b/include/git2/worktree.h @@ -125,6 +125,24 @@ typedef enum { GIT_WORKTREE_PRUNE_WORKING_TREE = 1u << 2, } git_worktree_prune_t; +/** + * Is the worktree prunable with the given set of flags? + * + * A worktree is not prunable in the following scenarios: + * + * - the worktree is linking to a valid on-disk worktree. The + * GIT_WORKTREE_PRUNE_VALID flag will cause this check to be + * ignored. + * - the worktree is not valid but locked. The + * GIT_WORKRTEE_PRUNE_LOCKED flag will cause this check to be + * ignored. + * + * If the worktree is not valid and not locked or if the above + * flags have been passed in, this function will return a + * positive value. + */ +GIT_EXTERN(int) git_worktree_is_prunable(git_worktree *wt, unsigned flags); + /** * Prune working tree * diff --git a/src/worktree.c b/src/worktree.c index a3fe07a23..5abc98945 100644 --- a/src/worktree.c +++ b/src/worktree.c @@ -357,11 +357,9 @@ out: return ret; } -int git_worktree_prune(git_worktree *wt, unsigned flags) +int git_worktree_is_prunable(git_worktree *wt, unsigned flags) { - git_buf reason = GIT_BUF_INIT, path = GIT_BUF_INIT; - char *wtpath; - int err; + git_buf reason = GIT_BUF_INIT; if ((flags & GIT_WORKTREE_PRUNE_LOCKED) == 0 && git_worktree_is_locked(&reason, wt)) @@ -369,15 +367,28 @@ int git_worktree_prune(git_worktree *wt, unsigned flags) if (!reason.size) git_buf_attach_notowned(&reason, "no reason given", 15); giterr_set(GITERR_WORKTREE, "Not pruning locked working tree: '%s'", reason.ptr); + git_buf_free(&reason); - err = -1; - goto out; + return 0; } if ((flags & GIT_WORKTREE_PRUNE_VALID) == 0 && git_worktree_validate(wt) == 0) { giterr_set(GITERR_WORKTREE, "Not pruning valid working tree"); + return 0; + } + + return 1; +} + +int git_worktree_prune(git_worktree *wt, unsigned flags) +{ + git_buf path = GIT_BUF_INIT; + char *wtpath; + int err; + + if (!git_worktree_is_prunable(wt, flags)) { err = -1; goto out; } @@ -415,7 +426,6 @@ int git_worktree_prune(git_worktree *wt, unsigned flags) goto out; out: - git_buf_free(&reason); git_buf_free(&path); return err; From cdb2c2a0bf9428ea188959f332e9f541a2fb2af1 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Mon, 13 Feb 2017 13:31:37 +0100 Subject: [PATCH 106/366] buffer: clarify how `git_buf_sanitize` handles non-NULL input When `git_buf_sanitize` gets called, it converts a buffer with NULL content to be correctly initialized. This is done by pointing it to `git_buf__initbuf`. While the method's documentation states this clearly, it may also lead to the conclusion that it will do the same to buffers which do _not_ have NULL contents. Clarify behavior when passing a buffer with non-NULL contents, where `git_buf_sanitize` will ensure that the contents are `\0`-terminated. --- src/buffer.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/buffer.h b/src/buffer.h index cdfca6d99..a76b2d771 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -66,7 +66,8 @@ extern int git_buf_try_grow( * library, when providing git_buf's, may wish to provide a NULL ptr for * ease of handling. The buffer routines, however, expect a non-NULL ptr * always. This helper method simply handles NULL input, converting to a - * git_buf__initbuf. + * git_buf__initbuf. If a buffer with a non-NULL ptr is passed in, this method + * assures that the buffer is '\0'-terminated. */ extern void git_buf_sanitize(git_buf *buf); From dc851d9eae21db8671118d798e55990e199af6af Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Mon, 13 Feb 2017 13:42:16 +0100 Subject: [PATCH 107/366] commit: clear user-provided buffers The functions `git_commit_header_field` and `git_commit_extract_signature` both receive buffers used to hand back the results to the user. While these functions called `git_buf_sanitize` on these buffers, this is not the right thing to do, as it will simply initialize or zero-terminate passed buffers. As we want to overwrite contents, we instead have to call `git_buf_clear` to completely reset them. --- include/git2/commit.h | 9 ++++++--- src/commit.c | 6 +++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/include/git2/commit.h b/include/git2/commit.h index 4cc637466..692b3bdd9 100644 --- a/include/git2/commit.h +++ b/include/git2/commit.h @@ -255,7 +255,8 @@ GIT_EXTERN(int) git_commit_nth_gen_ancestor( /** * Get an arbitrary header field * - * @param out the buffer to fill + * @param out the buffer to fill; existing content will be + * overwritten * @param commit the commit to look in * @param field the header field to return * @return 0 on succeess, GIT_ENOTFOUND if the field does not exist, @@ -270,8 +271,10 @@ GIT_EXTERN(int) git_commit_header_field(git_buf *out, const git_commit *commit, * `GITERR_INVALID`. If the commit does not have a signature, the * error class will be `GITERR_OBJECT`. * - * @param signature the signature block - * @param signed_data signed data; this is the commit contents minus the signature block + * @param signature the signature block; existing content will be + * overwritten + * @param signed_data signed data; this is the commit contents minus the signature block; + * existing content will be overwritten * @param repo the repository in which the commit exists * @param commit_id the commit from which to extract the data * @param field the name of the header field containing the signature diff --git a/src/commit.c b/src/commit.c index 87ab2ab60..89a4db115 100644 --- a/src/commit.c +++ b/src/commit.c @@ -642,7 +642,7 @@ int git_commit_header_field(git_buf *out, const git_commit *commit, const char * { const char *eol, *buf = commit->raw_header; - git_buf_sanitize(out); + git_buf_clear(out); while ((eol = strchr(buf, '\n'))) { /* We can skip continuations here */ @@ -706,8 +706,8 @@ int git_commit_extract_signature(git_buf *signature, git_buf *signed_data, git_r const char *h, *eol; int error; - git_buf_sanitize(signature); - git_buf_sanitize(signed_data); + git_buf_clear(signature); + git_buf_clear(signed_data); if (!field) field = "gpgsig"; From ade0d9c658fdfc68d8046935f6908f033fe7a529 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Mon, 13 Feb 2017 13:46:17 +0100 Subject: [PATCH 108/366] commit: avoid possible use-after-free When extracting a commit's signature, we first free the object and only afterwards put its signature contents into the result buffer. This works in most cases - the free'd object will normally be cached anyway, so we only end up decrementing its reference count without actually freeing its contents. But in some more exotic setups, where caching is disabled, this can definitly be a problem, as we might be the only instance currently holding a reference to this object. Fix this issue by first extracting the contents and freeing the object afterwards only. --- src/commit.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/commit.c b/src/commit.c index 89a4db115..05b70a983 100644 --- a/src/commit.c +++ b/src/commit.c @@ -766,8 +766,9 @@ int git_commit_extract_signature(git_buf *signature, git_buf *signed_data, git_r if (git_buf_oom(signature)) goto oom; + error = git_buf_puts(signed_data, eol+1); git_odb_object_free(obj); - return git_buf_puts(signed_data, eol+1); + return error; } giterr_set(GITERR_OBJECT, "this commit is not signed"); From 6da6b425d899b122fe4cab99ec109a5ae5e344f5 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Tue, 14 Feb 2017 11:13:32 +0100 Subject: [PATCH 109/366] refdb: catch additional per-worktree refs The upstream git.git project currently identifies all references inside of `refs/bisect/` as well as `HEAD` as per-worktree references. This is already incorrect and is currently being fixed by an in-flight topic [1]. The new behavior will be to match all pseudo-references outside of the `refs/` hierarchy as well as `refs/bisect/`. Our current behavior is to mark a selection of pseudo-references as per-worktree, only. This matches more pseudo-references than current git, but forgets about `refs/bisect/`. Adjust behavior to match the in-flight topic, that is classify the following references as per-worktree: - everything outside of `refs/` - everything inside of `refs/bisect/` [1]: <20170213152011.12050-1-pclouds@gmail.com> --- src/refdb_fs.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/refdb_fs.c b/src/refdb_fs.c index 3d690630e..def5302de 100644 --- a/src/refdb_fs.c +++ b/src/refdb_fs.c @@ -365,12 +365,17 @@ static const char *loose_parse_symbolic(git_buf *file_content) return refname_start; } +/* + * Returns whether a reference is stored per worktree or not. + * Per-worktree references are: + * + * - all pseudorefs, e.g. HEAD and MERGE_HEAD + * - all references stored inside of "refs/bisect/" + */ static bool is_per_worktree_ref(const char *ref_name) { - return strcmp("HEAD", ref_name) == 0 || - strcmp("FETCH_HEAD", ref_name) == 0 || - strcmp("MERGE_HEAD", ref_name) == 0 || - strcmp("ORIG_HEAD", ref_name) == 0; + return git__prefixcmp(ref_name, "refs/") != 0 || + git__prefixcmp(ref_name, "refs/bisect/") == 0; } static int loose_lookup( From 19874e293491f3864c21234c9aada5bac2856663 Mon Sep 17 00:00:00 2001 From: David Catmull Date: Thu, 16 Feb 2017 08:40:49 -0700 Subject: [PATCH 110/366] Minor comment fix --- include/git2/index.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/include/git2/index.h b/include/git2/index.h index e58b3287e..35af2e5bf 100644 --- a/include/git2/index.h +++ b/include/git2/index.h @@ -575,15 +575,16 @@ GIT_EXTERN(int) git_index_remove_bypath(git_index *index, const char *path); * This method will fail in bare index instances. * * The `pathspec` is a list of file names or shell glob patterns that will - * matched against files in the repository's working directory. Each file - * that matches will be added to the index (either updating an existing - * entry or adding a new entry). You can disable glob expansion and force - * exact matching with the `GIT_INDEX_ADD_DISABLE_PATHSPEC_MATCH` flag. + * be matched against files in the repository's working directory. Each + * file that matches will be added to the index (either updating an + * existing entry or adding a new entry). You can disable glob expansion + * and force exact matching with the `GIT_INDEX_ADD_DISABLE_PATHSPEC_MATCH` + * flag. * * Files that are ignored will be skipped (unlike `git_index_add_bypath`). * If a file is already tracked in the index, then it *will* be updated - * even if it is ignored. Pass the `GIT_INDEX_ADD_FORCE` flag to - * skip the checking of ignore rules. + * even if it is ignored. Pass the `GIT_INDEX_ADD_FORCE` flag to skip + * the checking of ignore rules. * * To emulate `git add -A` and generate an error if the pathspec contains * the exact path of an ignored file (when not using FORCE), add the From bff9b7a5a33c9aa8468d233676aba5dbad37b8d6 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 25 Jan 2017 14:12:13 +0100 Subject: [PATCH 111/366] strmap: remove unused macro `git_strmap_insert2` --- src/strmap.h | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/strmap.h b/src/strmap.h index 520984744..9fdab95bb 100644 --- a/src/strmap.h +++ b/src/strmap.h @@ -49,16 +49,6 @@ typedef khiter_t git_strmap_iter; kh_val(h, __pos) = val; \ } } while (0) -#define git_strmap_insert2(h, key, val, oldv, rval) do { \ - khiter_t __pos = kh_put(str, h, key, &rval); \ - if (rval >= 0) { \ - if (rval == 0) { \ - oldv = kh_val(h, __pos); \ - kh_key(h, __pos) = key; \ - } else { oldv = NULL; } \ - kh_val(h, __pos) = val; \ - } } while (0) - #define git_strmap_delete(h, key) do { \ khiter_t __pos = git_strmap_lookup_index(h, key); \ if (git_strmap_valid_index(h, __pos)) \ From a1b23df58cb704a1ac3e0670a26c804d8a08ed2e Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 27 Jan 2017 14:15:45 +0100 Subject: [PATCH 112/366] offmap: remove unused macro `git_offmap_insert2` --- src/offmap.h | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/offmap.h b/src/offmap.h index 0d0e51272..4476cf772 100644 --- a/src/offmap.h +++ b/src/offmap.h @@ -45,16 +45,6 @@ typedef khash_t(off) git_offmap; kh_val(h, __pos) = val; \ } } while (0) -#define git_offmap_insert2(h, key, val, oldv, rval) do { \ - khiter_t __pos = kh_put(off, h, key, &rval); \ - if (rval >= 0) { \ - if (rval == 0) { \ - oldv = kh_val(h, __pos); \ - kh_key(h, __pos) = key; \ - } else { oldv = NULL; } \ - kh_val(h, __pos) = val; \ - } } while (0) - #define git_offmap_delete(h, key) do { \ khiter_t __pos = git_offmap_lookup_index(h, key); \ if (git_offmap_valid_index(h, __pos)) \ From 63e914cbf4e6cb07d39b5a6f31749f78247ff594 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 25 Jan 2017 14:05:24 +0100 Subject: [PATCH 113/366] khash: avoid using `kh_size` directly --- src/cache.c | 10 +++++----- src/cache.h | 2 +- src/submodule.c | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/cache.c b/src/cache.c index 16ae9b397..e8fd207b1 100644 --- a/src/cache.c +++ b/src/cache.c @@ -47,11 +47,11 @@ void git_cache_dump_stats(git_cache *cache) { git_cached_obj *object; - if (kh_size(cache->map) == 0) + if (git_cache_size(cache) == 0) return; - printf("Cache %p: %d items cached, %"PRIdZ" bytes\n", - cache, kh_size(cache->map), cache->used_memory); + printf("Cache %p: %"PRIuZ" items cached, %"PRIdZ" bytes\n", + cache, git_cache_size(cache), cache->used_memory); kh_foreach_value(cache->map, object, { char oid_str[9]; @@ -81,7 +81,7 @@ static void clear_cache(git_cache *cache) { git_cached_obj *evict = NULL; - if (kh_size(cache->map) == 0) + if (git_cache_size(cache) == 0) return; kh_foreach_value(cache->map, evict, { @@ -119,7 +119,7 @@ static void cache_evict_entries(git_cache *cache) ssize_t evicted_memory = 0; /* do not infinite loop if there's not enough entries to evict */ - if (evict_count > kh_size(cache->map)) { + if (evict_count > git_cache_size(cache)) { clear_cache(cache); return; } diff --git a/src/cache.h b/src/cache.h index 697123739..0f0bfcf5d 100644 --- a/src/cache.h +++ b/src/cache.h @@ -53,7 +53,7 @@ void *git_cache_get_any(git_cache *cache, const git_oid *oid); GIT_INLINE(size_t) git_cache_size(git_cache *cache) { - return (size_t)kh_size(cache->map); + return (size_t)git_oidmap_size(cache->map); } GIT_INLINE(void) git_cached_obj_incref(void *_obj) diff --git a/src/submodule.c b/src/submodule.c index 3007d25df..0bc25cc29 100644 --- a/src/submodule.c +++ b/src/submodule.c @@ -555,7 +555,7 @@ int git_submodule_foreach( goto done; if (!(error = git_vector_init( - &snapshot, kh_size(submodules), submodule_cmp))) { + &snapshot, git_strmap_num_entries(submodules), submodule_cmp))) { git_strmap_foreach_value(submodules, sm, { if ((error = git_vector_insert(&snapshot, sm)) < 0) From 9694d9ba794b36ebc9fc186c43464a08c2f84c4d Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 25 Jan 2017 14:09:17 +0100 Subject: [PATCH 114/366] khash: avoid using `kh_foreach`/`kh_foreach_value` directly --- src/cache.c | 4 ++-- src/indexer.c | 5 +++-- src/odb_mempack.c | 2 +- src/pack.c | 18 ++++++------------ src/revwalk.c | 2 +- src/transaction.c | 18 ++++-------------- 6 files changed, 17 insertions(+), 32 deletions(-) diff --git a/src/cache.c b/src/cache.c index e8fd207b1..e7a565e05 100644 --- a/src/cache.c +++ b/src/cache.c @@ -53,7 +53,7 @@ void git_cache_dump_stats(git_cache *cache) printf("Cache %p: %"PRIuZ" items cached, %"PRIdZ" bytes\n", cache, git_cache_size(cache), cache->used_memory); - kh_foreach_value(cache->map, object, { + git_oidmap_foreach_value(cache->map, object, { char oid_str[9]; printf(" %s%c %s (%"PRIuZ")\n", git_object_type2string(object->type), @@ -84,7 +84,7 @@ static void clear_cache(git_cache *cache) if (git_cache_size(cache) == 0) return; - kh_foreach_value(cache->map, evict, { + git_oidmap_foreach_value(cache->map, evict, { git_cached_obj_decref(evict); }); diff --git a/src/indexer.c b/src/indexer.c index 606de2ef6..8b5fa6efd 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -1106,8 +1106,9 @@ void git_indexer_free(git_indexer *idx) if (idx->pack->idx_cache) { struct git_pack_entry *pentry; - kh_foreach_value( - idx->pack->idx_cache, pentry, { git__free(pentry); }); + git_oidmap_foreach_value(idx->pack->idx_cache, pentry, { + git__free(pentry); + }); git_oidmap_free(idx->pack->idx_cache); } diff --git a/src/odb_mempack.c b/src/odb_mempack.c index 84ed9c104..b9bdf0bb5 100644 --- a/src/odb_mempack.c +++ b/src/odb_mempack.c @@ -149,7 +149,7 @@ void git_mempack_reset(git_odb_backend *_backend) struct memory_packer_db *db = (struct memory_packer_db *)_backend; struct memobject *object = NULL; - kh_foreach_value(db->objects, object, { + git_oidmap_foreach_value(db->objects, object, { git__free(object); }); diff --git a/src/pack.c b/src/pack.c index 243719d9c..0f2fa5cdd 100644 --- a/src/pack.c +++ b/src/pack.c @@ -78,13 +78,12 @@ static void free_cache_object(void *o) static void cache_free(git_pack_cache *cache) { - khiter_t k; + git_pack_cache_entry *entry; if (cache->entries) { - for (k = kh_begin(cache->entries); k != kh_end(cache->entries); k++) { - if (kh_exist(cache->entries, k)) - free_cache_object(kh_value(cache->entries, k)); - } + git_offmap_foreach_value(cache->entries, entry, { + free_cache_object(entry); + }); git_offmap_free(cache->entries); cache->entries = NULL; @@ -135,18 +134,13 @@ static void free_lowest_entry(git_pack_cache *cache) git_pack_cache_entry *entry; khiter_t k; - for (k = kh_begin(cache->entries); k != kh_end(cache->entries); k++) { - if (!kh_exist(cache->entries, k)) - continue; - - entry = kh_value(cache->entries, k); - + git_offmap_foreach(cache->entries, k, entry, { if (entry && entry->refcount.val == 0) { cache->memory_used -= entry->raw.len; kh_del(off, cache->entries, k); free_cache_object(entry); } - } + }); } static int cache_add( diff --git a/src/revwalk.c b/src/revwalk.c index 8c370bcc8..c5fdb7ee3 100644 --- a/src/revwalk.c +++ b/src/revwalk.c @@ -702,7 +702,7 @@ void git_revwalk_reset(git_revwalk *walk) assert(walk); - kh_foreach_value(walk->commits, commit, { + git_oidmap_foreach_value(walk->commits, commit, { commit->seen = 0; commit->in_degree = 0; commit->topo_delay = 0; diff --git a/src/transaction.c b/src/transaction.c index 2c8a1e8bd..ffe374a86 100644 --- a/src/transaction.c +++ b/src/transaction.c @@ -323,7 +323,6 @@ static int update_target(git_refdb *db, transaction_node *node) int git_transaction_commit(git_transaction *tx) { transaction_node *node; - git_strmap_iter pos; int error = 0; assert(tx); @@ -335,11 +334,7 @@ int git_transaction_commit(git_transaction *tx) return error; } - for (pos = kh_begin(tx->locks); pos < kh_end(tx->locks); pos++) { - if (!git_strmap_has_data(tx->locks, pos)) - continue; - - node = git_strmap_value_at(tx->locks, pos); + git_strmap_foreach_value(tx->locks, node, { if (node->reflog) { if ((error = tx->db->backend->reflog_write(tx->db->backend, node->reflog)) < 0) return error; @@ -349,7 +344,7 @@ int git_transaction_commit(git_transaction *tx) if ((error = update_target(tx->db, node)) < 0) return error; } - } + }); return 0; } @@ -358,7 +353,6 @@ void git_transaction_free(git_transaction *tx) { transaction_node *node; git_pool pool; - git_strmap_iter pos; assert(tx); @@ -373,16 +367,12 @@ void git_transaction_free(git_transaction *tx) } /* start by unlocking the ones we've left hanging, if any */ - for (pos = kh_begin(tx->locks); pos < kh_end(tx->locks); pos++) { - if (!git_strmap_has_data(tx->locks, pos)) - continue; - - node = git_strmap_value_at(tx->locks, pos); + git_strmap_foreach_value(tx->locks, node, { if (node->committed) continue; git_refdb_unlock(tx->db, node->payload, false, false, NULL, NULL, NULL); - } + }); git_refdb_free(tx->db); git_strmap_free(tx->locks); From 036daa59e94bbe1a14ccd8fa018618393a0c62fb Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 25 Jan 2017 14:11:42 +0100 Subject: [PATCH 115/366] khash: use `git_map_exists` where applicable --- src/indexer.c | 4 +--- src/odb_mempack.c | 7 +------ src/oidmap.h | 2 ++ src/pack-objects.c | 3 +-- src/pack.c | 2 +- 5 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/indexer.c b/src/indexer.c index 8b5fa6efd..b5d5fd0d2 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -333,9 +333,7 @@ on_error: GIT_INLINE(bool) has_entry(git_indexer *idx, git_oid *id) { - khiter_t k; - k = kh_get(oid, idx->pack->idx_cache, id); - return (k != kh_end(idx->pack->idx_cache)); + return git_oidmap_exists(idx->pack->idx_cache, id); } static int save_entry(git_indexer *idx, struct entry *entry, struct git_pack_entry *pentry, git_off_t entry_start) diff --git a/src/odb_mempack.c b/src/odb_mempack.c index b9bdf0bb5..6aa9ad89a 100644 --- a/src/odb_mempack.c +++ b/src/odb_mempack.c @@ -72,13 +72,8 @@ static int impl__write(git_odb_backend *_backend, const git_oid *oid, const void static int impl__exists(git_odb_backend *backend, const git_oid *oid) { struct memory_packer_db *db = (struct memory_packer_db *)backend; - khiter_t pos; - pos = kh_get(oid, db->objects, oid); - if (pos != kh_end(db->objects)) - return 1; - - return 0; + return git_oidmap_exists(db->objects, oid); } static int impl__read(void **buffer_p, size_t *len_p, git_otype *type_p, git_odb_backend *backend, const git_oid *oid) diff --git a/src/oidmap.h b/src/oidmap.h index 2cf208f53..5364862d2 100644 --- a/src/oidmap.h +++ b/src/oidmap.h @@ -36,6 +36,8 @@ GIT_INLINE(khint_t) git_oidmap_hash(const git_oid *oid) #define git_oidmap_lookup_index(h, k) kh_get(oid, h, k) #define git_oidmap_valid_index(h, idx) (idx != kh_end(h)) +#define git_oidmap_exists(h, k) (kh_get(oid, h, k) != kh_end(h)) + #define git_oidmap_value_at(h, idx) kh_val(h, idx) #define git_oidmap_insert(h, key, val, rval) do { \ diff --git a/src/pack-objects.c b/src/pack-objects.c index 2e5de98ab..203816710 100644 --- a/src/pack-objects.c +++ b/src/pack-objects.c @@ -216,8 +216,7 @@ int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid, /* If the object already exists in the hash table, then we don't * have any work to do */ - pos = kh_get(oid, pb->object_ix, oid); - if (pos != kh_end(pb->object_ix)) + if (git_oidmap_exists(pb->object_ix, oid)) return 0; if (pb->nr_objects >= pb->nr_alloc) { diff --git a/src/pack.c b/src/pack.c index 0f2fa5cdd..8a204342d 100644 --- a/src/pack.c +++ b/src/pack.c @@ -164,7 +164,7 @@ static int cache_add( return -1; } /* Add it to the cache if nobody else has */ - exists = kh_get(off, cache->entries, offset) != kh_end(cache->entries); + exists = git_offmap_exists(cache->entries, offset); if (!exists) { while (cache->memory_used + base->len > cache->memory_limit) free_lowest_entry(cache); From 64e46dc3b54bb7071b5d21e16db8ebf5a44eb8ed Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 25 Jan 2017 14:14:12 +0100 Subject: [PATCH 116/366] khash: avoid using `kh_end` directly --- src/cache.c | 6 +++--- src/odb_mempack.c | 4 ++-- src/oidmap.h | 3 +++ src/pack-objects.c | 2 +- src/pack.c | 4 ++-- src/revwalk.c | 2 +- tests/core/oidmap.c | 8 ++++---- 7 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/cache.c b/src/cache.c index e7a565e05..7ababc9df 100644 --- a/src/cache.c +++ b/src/cache.c @@ -125,7 +125,7 @@ static void cache_evict_entries(git_cache *cache) } while (evict_count > 0) { - khiter_t pos = seed++ % kh_end(cache->map); + khiter_t pos = seed++ % git_oidmap_end(cache->map); if (kh_exist(cache->map, pos)) { git_cached_obj *evict = kh_val(cache->map, pos); @@ -157,7 +157,7 @@ static void *cache_get(git_cache *cache, const git_oid *oid, unsigned int flags) return NULL; pos = kh_get(oid, cache->map, oid); - if (pos != kh_end(cache->map)) { + if (git_oidmap_valid_index(cache->map, pos)) { entry = kh_val(cache->map, pos); if (flags && entry->flags != flags) { @@ -196,7 +196,7 @@ static void *cache_store(git_cache *cache, git_cached_obj *entry) pos = kh_get(oid, cache->map, &entry->oid); /* not found */ - if (pos == kh_end(cache->map)) { + if (!git_oidmap_valid_index(cache->map, pos)) { int rval; pos = kh_put(oid, cache->map, &entry->oid, &rval); diff --git a/src/odb_mempack.c b/src/odb_mempack.c index 6aa9ad89a..fc5e0f1d4 100644 --- a/src/odb_mempack.c +++ b/src/odb_mempack.c @@ -83,7 +83,7 @@ static int impl__read(void **buffer_p, size_t *len_p, git_otype *type_p, git_odb khiter_t pos; pos = kh_get(oid, db->objects, oid); - if (pos == kh_end(db->objects)) + if (!git_oidmap_valid_index(db->objects, pos)) return GIT_ENOTFOUND; obj = kh_val(db->objects, pos); @@ -104,7 +104,7 @@ static int impl__read_header(size_t *len_p, git_otype *type_p, git_odb_backend * khiter_t pos; pos = kh_get(oid, db->objects, oid); - if (pos == kh_end(db->objects)) + if (!git_oidmap_valid_index(db->objects, pos)) return GIT_ENOTFOUND; obj = kh_val(db->objects, pos); diff --git a/src/oidmap.h b/src/oidmap.h index 5364862d2..c0c45027d 100644 --- a/src/oidmap.h +++ b/src/oidmap.h @@ -49,6 +49,9 @@ GIT_INLINE(khint_t) git_oidmap_hash(const git_oid *oid) #define git_oidmap_foreach_value kh_foreach_value +#define git_oidmap_begin kh_begin +#define git_oidmap_end kh_end + #define git_oidmap_size(h) kh_size(h) #define git_oidmap_clear(h) kh_clear(oid, h) diff --git a/src/pack-objects.c b/src/pack-objects.c index 203816710..3517de479 100644 --- a/src/pack-objects.c +++ b/src/pack-objects.c @@ -517,7 +517,7 @@ static int cb_tag_foreach(const char *name, git_oid *oid, void *data) GIT_UNUSED(name); pos = kh_get(oid, pb->object_ix, oid); - if (pos == kh_end(pb->object_ix)) + if (!git_oidmap_valid_index(pb->object_ix, pos)) return 0; po = kh_value(pb->object_ix, pos); diff --git a/src/pack.c b/src/pack.c index 8a204342d..e23d50110 100644 --- a/src/pack.c +++ b/src/pack.c @@ -118,7 +118,7 @@ static git_pack_cache_entry *cache_get(git_pack_cache *cache, git_off_t offset) return NULL; k = kh_get(off, cache->entries, offset); - if (k != kh_end(cache->entries)) { /* found it */ + if (git_offmap_valid_index(cache->entries, k)) { /* found it */ entry = kh_value(cache->entries, k); git_atomic_inc(&entry->refcount); entry->last_usage = cache->use_ctr++; @@ -957,7 +957,7 @@ git_off_t get_delta_base( git_oid_fromraw(&oid, base_info); k = kh_get(oid, p->idx_cache, &oid); - if (k != kh_end(p->idx_cache)) { + if (git_oidmap_valid_index(p->idx_cache, k)) { *curpos += 20; return ((struct git_pack_entry *)kh_value(p->idx_cache, k))->offset; } else { diff --git a/src/revwalk.c b/src/revwalk.c index c5fdb7ee3..8805aa8fa 100644 --- a/src/revwalk.c +++ b/src/revwalk.c @@ -26,7 +26,7 @@ git_commit_list_node *git_revwalk__commit_lookup( /* lookup and reserve space if not already present */ pos = kh_get(oid, walk->commits, oid); - if (pos != kh_end(walk->commits)) + if (git_oidmap_valid_index(walk->commits, pos)) return kh_value(walk->commits, pos); commit = git_commit_list_alloc_node(walk); diff --git a/tests/core/oidmap.c b/tests/core/oidmap.c index 556a6ca4a..aea069843 100644 --- a/tests/core/oidmap.c +++ b/tests/core/oidmap.c @@ -34,7 +34,7 @@ void test_core_oidmap__basic(void) int ret; pos = kh_get(oid, map, &items[i].oid); - cl_assert(pos == kh_end(map)); + cl_assert(!git_oidmap_valid_index(map, pos)); pos = kh_put(oid, map, &items[i].oid, &ret); cl_assert(ret != 0); @@ -47,7 +47,7 @@ void test_core_oidmap__basic(void) khiter_t pos; pos = kh_get(oid, map, &items[i].oid); - cl_assert(pos != kh_end(map)); + cl_assert(git_oidmap_valid_index(map, pos)); cl_assert_equal_p(kh_val(map, pos), &items[i]); } @@ -88,7 +88,7 @@ void test_core_oidmap__hash_collision(void) int ret; pos = kh_get(oid, map, &items[i].oid); - cl_assert(pos == kh_end(map)); + cl_assert(!git_oidmap_valid_index(map, pos)); pos = kh_put(oid, map, &items[i].oid, &ret); cl_assert(ret != 0); @@ -101,7 +101,7 @@ void test_core_oidmap__hash_collision(void) khiter_t pos; pos = kh_get(oid, map, &items[i].oid); - cl_assert(pos != kh_end(map)); + cl_assert(git_oidmap_valid_index(map, pos)); cl_assert_equal_p(kh_val(map, pos), &items[i]); } From a853c5272359f7b5b1f0648cf16cefe7434840b2 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 25 Jan 2017 14:14:32 +0100 Subject: [PATCH 117/366] khash: avoid using `kh_get` directly --- src/cache.c | 4 ++-- src/odb_mempack.c | 4 ++-- src/pack-objects.c | 2 +- src/pack.c | 4 ++-- src/revwalk.c | 2 +- tests/core/oidmap.c | 8 ++++---- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/cache.c b/src/cache.c index 7ababc9df..79885c41e 100644 --- a/src/cache.c +++ b/src/cache.c @@ -156,7 +156,7 @@ static void *cache_get(git_cache *cache, const git_oid *oid, unsigned int flags) if (!git_cache__enabled || git_rwlock_rdlock(&cache->lock) < 0) return NULL; - pos = kh_get(oid, cache->map, oid); + pos = git_oidmap_lookup_index(cache->map, oid); if (git_oidmap_valid_index(cache->map, pos)) { entry = kh_val(cache->map, pos); @@ -193,7 +193,7 @@ static void *cache_store(git_cache *cache, git_cached_obj *entry) if (git_cache__current_storage.val > git_cache__max_storage) cache_evict_entries(cache); - pos = kh_get(oid, cache->map, &entry->oid); + pos = git_oidmap_lookup_index(cache->map, &entry->oid); /* not found */ if (!git_oidmap_valid_index(cache->map, pos)) { diff --git a/src/odb_mempack.c b/src/odb_mempack.c index fc5e0f1d4..b55ce7310 100644 --- a/src/odb_mempack.c +++ b/src/odb_mempack.c @@ -82,7 +82,7 @@ static int impl__read(void **buffer_p, size_t *len_p, git_otype *type_p, git_odb struct memobject *obj = NULL; khiter_t pos; - pos = kh_get(oid, db->objects, oid); + pos = git_oidmap_lookup_index(db->objects, oid); if (!git_oidmap_valid_index(db->objects, pos)) return GIT_ENOTFOUND; @@ -103,7 +103,7 @@ static int impl__read_header(size_t *len_p, git_otype *type_p, git_odb_backend * struct memobject *obj = NULL; khiter_t pos; - pos = kh_get(oid, db->objects, oid); + pos = git_oidmap_lookup_index(db->objects, oid); if (!git_oidmap_valid_index(db->objects, pos)) return GIT_ENOTFOUND; diff --git a/src/pack-objects.c b/src/pack-objects.c index 3517de479..e2b24e8e5 100644 --- a/src/pack-objects.c +++ b/src/pack-objects.c @@ -516,7 +516,7 @@ static int cb_tag_foreach(const char *name, git_oid *oid, void *data) GIT_UNUSED(name); - pos = kh_get(oid, pb->object_ix, oid); + pos = git_oidmap_lookup_index(pb->object_ix, oid); if (!git_oidmap_valid_index(pb->object_ix, pos)) return 0; diff --git a/src/pack.c b/src/pack.c index e23d50110..43ef09801 100644 --- a/src/pack.c +++ b/src/pack.c @@ -117,7 +117,7 @@ static git_pack_cache_entry *cache_get(git_pack_cache *cache, git_off_t offset) if (git_mutex_lock(&cache->lock) < 0) return NULL; - k = kh_get(off, cache->entries, offset); + k = git_offmap_lookup_index(cache->entries, offset); if (git_offmap_valid_index(cache->entries, k)) { /* found it */ entry = kh_value(cache->entries, k); git_atomic_inc(&entry->refcount); @@ -956,7 +956,7 @@ git_off_t get_delta_base( git_oid oid; git_oid_fromraw(&oid, base_info); - k = kh_get(oid, p->idx_cache, &oid); + k = git_oidmap_lookup_index(p->idx_cache, &oid); if (git_oidmap_valid_index(p->idx_cache, k)) { *curpos += 20; return ((struct git_pack_entry *)kh_value(p->idx_cache, k))->offset; diff --git a/src/revwalk.c b/src/revwalk.c index 8805aa8fa..752666509 100644 --- a/src/revwalk.c +++ b/src/revwalk.c @@ -25,7 +25,7 @@ git_commit_list_node *git_revwalk__commit_lookup( int ret; /* lookup and reserve space if not already present */ - pos = kh_get(oid, walk->commits, oid); + pos = git_oidmap_lookup_index(walk->commits, oid); if (git_oidmap_valid_index(walk->commits, pos)) return kh_value(walk->commits, pos); diff --git a/tests/core/oidmap.c b/tests/core/oidmap.c index aea069843..2255e3936 100644 --- a/tests/core/oidmap.c +++ b/tests/core/oidmap.c @@ -33,7 +33,7 @@ void test_core_oidmap__basic(void) khiter_t pos; int ret; - pos = kh_get(oid, map, &items[i].oid); + pos = git_oidmap_lookup_index(map, &items[i].oid); cl_assert(!git_oidmap_valid_index(map, pos)); pos = kh_put(oid, map, &items[i].oid, &ret); @@ -46,7 +46,7 @@ void test_core_oidmap__basic(void) for (i = 0; i < NITEMS; ++i) { khiter_t pos; - pos = kh_get(oid, map, &items[i].oid); + pos = git_oidmap_lookup_index(map, &items[i].oid); cl_assert(git_oidmap_valid_index(map, pos)); cl_assert_equal_p(kh_val(map, pos), &items[i]); @@ -87,7 +87,7 @@ void test_core_oidmap__hash_collision(void) khiter_t pos; int ret; - pos = kh_get(oid, map, &items[i].oid); + pos = git_oidmap_lookup_index(map, &items[i].oid); cl_assert(!git_oidmap_valid_index(map, pos)); pos = kh_put(oid, map, &items[i].oid, &ret); @@ -100,7 +100,7 @@ void test_core_oidmap__hash_collision(void) for (i = 0; i < NITEMS; ++i) { khiter_t pos; - pos = kh_get(oid, map, &items[i].oid); + pos = git_oidmap_lookup_index(map, &items[i].oid); cl_assert(git_oidmap_valid_index(map, pos)); cl_assert_equal_p(kh_val(map, pos), &items[i]); From c37b069b9f324c3e68ca5ddfce9588aabe97f346 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 25 Jan 2017 14:16:35 +0100 Subject: [PATCH 118/366] khash: avoid using `kh_clear` directly --- src/cache.c | 2 +- src/pack-objects.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cache.c b/src/cache.c index 79885c41e..0309c3d8e 100644 --- a/src/cache.c +++ b/src/cache.c @@ -88,7 +88,7 @@ static void clear_cache(git_cache *cache) git_cached_obj_decref(evict); }); - kh_clear(oid, cache->map); + git_oidmap_clear(cache->map); git_atomic_ssize_add(&git_cache__current_storage, -cache->used_memory); cache->used_memory = 0; } diff --git a/src/pack-objects.c b/src/pack-objects.c index e2b24e8e5..e463820e4 100644 --- a/src/pack-objects.c +++ b/src/pack-objects.c @@ -197,7 +197,7 @@ static void rehash(git_packbuilder *pb) size_t i; int ret; - kh_clear(oid, pb->object_ix); + git_oidmap_clear(pb->object_ix); for (i = 0, po = pb->object_list; i < pb->nr_objects; i++, po++) { pos = kh_put(oid, pb->object_ix, &po->id, &ret); kh_value(pb->object_ix, pos) = po; From 76e671a653360f816765fe55b367d29946361490 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 25 Jan 2017 14:20:56 +0100 Subject: [PATCH 119/366] khash: avoid using `kh_exist` directly --- src/cache.c | 2 +- src/oidmap.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cache.c b/src/cache.c index 0309c3d8e..ae42216c9 100644 --- a/src/cache.c +++ b/src/cache.c @@ -127,7 +127,7 @@ static void cache_evict_entries(git_cache *cache) while (evict_count > 0) { khiter_t pos = seed++ % git_oidmap_end(cache->map); - if (kh_exist(cache->map, pos)) { + if (git_oidmap_has_data(cache->map, pos)) { git_cached_obj *evict = kh_val(cache->map, pos); evict_count--; diff --git a/src/oidmap.h b/src/oidmap.h index c0c45027d..6afc8c916 100644 --- a/src/oidmap.h +++ b/src/oidmap.h @@ -37,6 +37,7 @@ GIT_INLINE(khint_t) git_oidmap_hash(const git_oid *oid) #define git_oidmap_valid_index(h, idx) (idx != kh_end(h)) #define git_oidmap_exists(h, k) (kh_get(oid, h, k) != kh_end(h)) +#define git_oidmap_has_data(h, idx) kh_exist(h, idx) #define git_oidmap_value_at(h, idx) kh_val(h, idx) From cb18386f72f07fc7316a0be892b98185d4aef7ce Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 25 Jan 2017 14:26:58 +0100 Subject: [PATCH 120/366] khash: avoid using `kh_val`/`kh_value` directly --- src/cache.c | 10 +++++----- src/indexer.c | 4 ++-- src/odb_mempack.c | 6 +++--- src/pack-objects.c | 6 +++--- src/pack.c | 6 +++--- src/revwalk.c | 4 ++-- src/sortedcache.c | 2 +- tests/core/oidmap.c | 8 ++++---- 8 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/cache.c b/src/cache.c index ae42216c9..c5f576a80 100644 --- a/src/cache.c +++ b/src/cache.c @@ -128,7 +128,7 @@ static void cache_evict_entries(git_cache *cache) khiter_t pos = seed++ % git_oidmap_end(cache->map); if (git_oidmap_has_data(cache->map, pos)) { - git_cached_obj *evict = kh_val(cache->map, pos); + git_cached_obj *evict = git_oidmap_value_at(cache->map, pos); evict_count--; evicted_memory += evict->size; @@ -158,7 +158,7 @@ static void *cache_get(git_cache *cache, const git_oid *oid, unsigned int flags) pos = git_oidmap_lookup_index(cache->map, oid); if (git_oidmap_valid_index(cache->map, pos)) { - entry = kh_val(cache->map, pos); + entry = git_oidmap_value_at(cache->map, pos); if (flags && entry->flags != flags) { entry = NULL; @@ -202,7 +202,7 @@ static void *cache_store(git_cache *cache, git_cached_obj *entry) pos = kh_put(oid, cache->map, &entry->oid, &rval); if (rval >= 0) { kh_key(cache->map, pos) = &entry->oid; - kh_val(cache->map, pos) = entry; + git_oidmap_value_at(cache->map, pos) = entry; git_cached_obj_incref(entry); cache->used_memory += entry->size; git_atomic_ssize_add(&git_cache__current_storage, (ssize_t)entry->size); @@ -210,7 +210,7 @@ static void *cache_store(git_cache *cache, git_cached_obj *entry) } /* found */ else { - git_cached_obj *stored_entry = kh_val(cache->map, pos); + git_cached_obj *stored_entry = git_oidmap_value_at(cache->map, pos); if (stored_entry->flags == entry->flags) { git_cached_obj_decref(entry); @@ -222,7 +222,7 @@ static void *cache_store(git_cache *cache, git_cached_obj *entry) git_cached_obj_incref(entry); kh_key(cache->map, pos) = &entry->oid; - kh_val(cache->map, pos) = entry; + git_oidmap_value_at(cache->map, pos) = entry; } else { /* NO OP */ } diff --git a/src/indexer.c b/src/indexer.c index b5d5fd0d2..303dd7cc7 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -308,7 +308,7 @@ static int store_object(git_indexer *idx) } - kh_value(idx->pack->idx_cache, k) = pentry; + git_oidmap_value_at(idx->pack->idx_cache, k) = pentry; git_oid_cpy(&entry->oid, &oid); @@ -356,7 +356,7 @@ static int save_entry(git_indexer *idx, struct entry *entry, struct git_pack_ent return -1; } - kh_value(idx->pack->idx_cache, k) = pentry; + git_oidmap_value_at(idx->pack->idx_cache, k) = pentry; /* Add the object to the list */ if (git_vector_insert(&idx->objects, entry) < 0) diff --git a/src/odb_mempack.c b/src/odb_mempack.c index b55ce7310..1b8987ef8 100644 --- a/src/odb_mempack.c +++ b/src/odb_mempack.c @@ -58,7 +58,7 @@ static int impl__write(git_odb_backend *_backend, const git_oid *oid, const void obj->type = type; kh_key(db->objects, pos) = &obj->oid; - kh_val(db->objects, pos) = obj; + git_oidmap_value_at(db->objects, pos) = obj; if (type == GIT_OBJ_COMMIT) { struct memobject **store = git_array_alloc(db->commits); @@ -86,7 +86,7 @@ static int impl__read(void **buffer_p, size_t *len_p, git_otype *type_p, git_odb if (!git_oidmap_valid_index(db->objects, pos)) return GIT_ENOTFOUND; - obj = kh_val(db->objects, pos); + obj = git_oidmap_value_at(db->objects, pos); *len_p = obj->len; *type_p = obj->type; @@ -107,7 +107,7 @@ static int impl__read_header(size_t *len_p, git_otype *type_p, git_odb_backend * if (!git_oidmap_valid_index(db->objects, pos)) return GIT_ENOTFOUND; - obj = kh_val(db->objects, pos); + obj = git_oidmap_value_at(db->objects, pos); *len_p = obj->len; *type_p = obj->type; diff --git a/src/pack-objects.c b/src/pack-objects.c index e463820e4..01286fa56 100644 --- a/src/pack-objects.c +++ b/src/pack-objects.c @@ -200,7 +200,7 @@ static void rehash(git_packbuilder *pb) git_oidmap_clear(pb->object_ix); for (i = 0, po = pb->object_list; i < pb->nr_objects; i++, po++) { pos = kh_put(oid, pb->object_ix, &po->id, &ret); - kh_value(pb->object_ix, pos) = po; + git_oidmap_value_at(pb->object_ix, pos) = po; } } @@ -252,7 +252,7 @@ int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid, return ret; } assert(ret != 0); - kh_value(pb->object_ix, pos) = po; + git_oidmap_value_at(pb->object_ix, pos) = po; pb->done = false; @@ -520,7 +520,7 @@ static int cb_tag_foreach(const char *name, git_oid *oid, void *data) if (!git_oidmap_valid_index(pb->object_ix, pos)) return 0; - po = kh_value(pb->object_ix, pos); + po = git_oidmap_value_at(pb->object_ix, pos); po->tagged = 1; /* TODO: peel objects */ diff --git a/src/pack.c b/src/pack.c index 43ef09801..4c2b9ebe0 100644 --- a/src/pack.c +++ b/src/pack.c @@ -119,7 +119,7 @@ static git_pack_cache_entry *cache_get(git_pack_cache *cache, git_off_t offset) k = git_offmap_lookup_index(cache->entries, offset); if (git_offmap_valid_index(cache->entries, k)) { /* found it */ - entry = kh_value(cache->entries, k); + entry = git_offmap_value_at(cache->entries, k); git_atomic_inc(&entry->refcount); entry->last_usage = cache->use_ctr++; } @@ -171,7 +171,7 @@ static int cache_add( k = kh_put(off, cache->entries, offset, &error); assert(error != 0); - kh_value(cache->entries, k) = entry; + git_oidmap_value_at(cache->entries, k) = entry; cache->memory_used += entry->raw.len; *cached_out = entry; @@ -959,7 +959,7 @@ git_off_t get_delta_base( k = git_oidmap_lookup_index(p->idx_cache, &oid); if (git_oidmap_valid_index(p->idx_cache, k)) { *curpos += 20; - return ((struct git_pack_entry *)kh_value(p->idx_cache, k))->offset; + return ((struct git_pack_entry *)git_oidmap_value_at(p->idx_cache, k))->offset; } else { /* If we're building an index, don't try to find the pack * entry; we just haven't seen it yet. We'll make diff --git a/src/revwalk.c b/src/revwalk.c index 752666509..32a4ff906 100644 --- a/src/revwalk.c +++ b/src/revwalk.c @@ -27,7 +27,7 @@ git_commit_list_node *git_revwalk__commit_lookup( /* lookup and reserve space if not already present */ pos = git_oidmap_lookup_index(walk->commits, oid); if (git_oidmap_valid_index(walk->commits, pos)) - return kh_value(walk->commits, pos); + return git_oidmap_value_at(walk->commits, pos); commit = git_commit_list_alloc_node(walk); if (commit == NULL) @@ -37,7 +37,7 @@ git_commit_list_node *git_revwalk__commit_lookup( pos = kh_put(oid, walk->commits, &commit->oid, &ret); assert(ret != 0); - kh_value(walk->commits, pos) = commit; + git_oidmap_value_at(walk->commits, pos) = commit; return commit; } diff --git a/src/sortedcache.c b/src/sortedcache.c index c5e338f75..48e8b6c71 100644 --- a/src/sortedcache.c +++ b/src/sortedcache.c @@ -300,7 +300,7 @@ int git_sortedcache_upsert(void **out, git_sortedcache *sc, const char *key) if (!error) kh_key(sc->map, pos) = item_key; - kh_val(sc->map, pos) = item; + git_strmap_value_at(sc->map, pos) = item; error = git_vector_insert(&sc->items, item); if (error < 0) diff --git a/tests/core/oidmap.c b/tests/core/oidmap.c index 2255e3936..61d75e9d1 100644 --- a/tests/core/oidmap.c +++ b/tests/core/oidmap.c @@ -39,7 +39,7 @@ void test_core_oidmap__basic(void) pos = kh_put(oid, map, &items[i].oid, &ret); cl_assert(ret != 0); - kh_val(map, pos) = &items[i]; + git_oidmap_value_at(map, pos) = &items[i]; } @@ -49,7 +49,7 @@ void test_core_oidmap__basic(void) pos = git_oidmap_lookup_index(map, &items[i].oid); cl_assert(git_oidmap_valid_index(map, pos)); - cl_assert_equal_p(kh_val(map, pos), &items[i]); + cl_assert_equal_p(git_oidmap_value_at(map, pos), &items[i]); } git_oidmap_free(map); @@ -93,7 +93,7 @@ void test_core_oidmap__hash_collision(void) pos = kh_put(oid, map, &items[i].oid, &ret); cl_assert(ret != 0); - kh_val(map, pos) = &items[i]; + git_oidmap_value_at(map, pos) = &items[i]; } @@ -103,7 +103,7 @@ void test_core_oidmap__hash_collision(void) pos = git_oidmap_lookup_index(map, &items[i].oid); cl_assert(git_oidmap_valid_index(map, pos)); - cl_assert_equal_p(kh_val(map, pos), &items[i]); + cl_assert_equal_p(git_oidmap_value_at(map, pos), &items[i]); } git_oidmap_free(map); From 71a54317efc465c0ccba8fd8d588d03087433048 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 25 Jan 2017 14:32:23 +0100 Subject: [PATCH 121/366] khash: avoid using `kh_key` directly --- src/cache.c | 6 ++---- src/odb_mempack.c | 2 +- src/oidmap.h | 1 + src/sortedcache.c | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/cache.c b/src/cache.c index c5f576a80..89c46ef7d 100644 --- a/src/cache.c +++ b/src/cache.c @@ -199,10 +199,8 @@ static void *cache_store(git_cache *cache, git_cached_obj *entry) if (!git_oidmap_valid_index(cache->map, pos)) { int rval; - pos = kh_put(oid, cache->map, &entry->oid, &rval); + git_oidmap_insert(cache->map, &entry->oid, entry, rval); if (rval >= 0) { - kh_key(cache->map, pos) = &entry->oid; - git_oidmap_value_at(cache->map, pos) = entry; git_cached_obj_incref(entry); cache->used_memory += entry->size; git_atomic_ssize_add(&git_cache__current_storage, (ssize_t)entry->size); @@ -221,7 +219,7 @@ static void *cache_store(git_cache *cache, git_cached_obj *entry) git_cached_obj_decref(stored_entry); git_cached_obj_incref(entry); - kh_key(cache->map, pos) = &entry->oid; + git_oidmap_key(cache->map, pos) = &entry->oid; git_oidmap_value_at(cache->map, pos) = entry; } else { /* NO OP */ diff --git a/src/odb_mempack.c b/src/odb_mempack.c index 1b8987ef8..3165710b5 100644 --- a/src/odb_mempack.c +++ b/src/odb_mempack.c @@ -57,7 +57,7 @@ static int impl__write(git_odb_backend *_backend, const git_oid *oid, const void obj->len = len; obj->type = type; - kh_key(db->objects, pos) = &obj->oid; + git_oidmap_key(db->objects, pos) = &obj->oid; git_oidmap_value_at(db->objects, pos) = obj; if (type == GIT_OBJ_COMMIT) { diff --git a/src/oidmap.h b/src/oidmap.h index 6afc8c916..4fab99ae0 100644 --- a/src/oidmap.h +++ b/src/oidmap.h @@ -39,6 +39,7 @@ GIT_INLINE(khint_t) git_oidmap_hash(const git_oid *oid) #define git_oidmap_exists(h, k) (kh_get(oid, h, k) != kh_end(h)) #define git_oidmap_has_data(h, idx) kh_exist(h, idx) +#define git_oidmap_key(h, idx) kh_key(h, idx) #define git_oidmap_value_at(h, idx) kh_val(h, idx) #define git_oidmap_insert(h, key, val, rval) do { \ diff --git a/src/sortedcache.c b/src/sortedcache.c index 48e8b6c71..199fa2484 100644 --- a/src/sortedcache.c +++ b/src/sortedcache.c @@ -299,7 +299,7 @@ int git_sortedcache_upsert(void **out, git_sortedcache *sc, const char *key) goto done; if (!error) - kh_key(sc->map, pos) = item_key; + git_strmap_key(sc->map, pos) = item_key; git_strmap_value_at(sc->map, pos) = item; error = git_vector_insert(&sc->items, item); From a8cd560b10149208aabcfe515b2e1b6c5be6388f Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 25 Jan 2017 14:41:17 +0100 Subject: [PATCH 122/366] khash: avoid using `kh_del` directly --- src/cache.c | 2 +- src/oidmap.h | 5 +++-- src/pack.c | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/cache.c b/src/cache.c index 89c46ef7d..965fc0c9b 100644 --- a/src/cache.c +++ b/src/cache.c @@ -134,7 +134,7 @@ static void cache_evict_entries(git_cache *cache) evicted_memory += evict->size; git_cached_obj_decref(evict); - kh_del(oid, cache->map, pos); + git_oidmap_delete_at(cache->map, pos); } } diff --git a/src/oidmap.h b/src/oidmap.h index 4fab99ae0..8eb8e28c0 100644 --- a/src/oidmap.h +++ b/src/oidmap.h @@ -39,8 +39,9 @@ GIT_INLINE(khint_t) git_oidmap_hash(const git_oid *oid) #define git_oidmap_exists(h, k) (kh_get(oid, h, k) != kh_end(h)) #define git_oidmap_has_data(h, idx) kh_exist(h, idx) -#define git_oidmap_key(h, idx) kh_key(h, idx) -#define git_oidmap_value_at(h, idx) kh_val(h, idx) +#define git_oidmap_key(h, idx) kh_key(h, idx) +#define git_oidmap_value_at(h, idx) kh_val(h, idx) +#define git_oidmap_delete_at(h, idx) kh_del(oid, h, idx) #define git_oidmap_insert(h, key, val, rval) do { \ khiter_t __pos = kh_put(oid, h, key, &rval); \ diff --git a/src/pack.c b/src/pack.c index 4c2b9ebe0..fe4a65c53 100644 --- a/src/pack.c +++ b/src/pack.c @@ -137,7 +137,7 @@ static void free_lowest_entry(git_pack_cache *cache) git_offmap_foreach(cache->entries, k, entry, { if (entry && entry->refcount.val == 0) { cache->memory_used -= entry->raw.len; - kh_del(off, cache->entries, k); + git_offmap_delete_at(cache->entries, k); free_cache_object(entry); } }); From f31cb45ad2ca46cc743dfadf5ac8b916cbe4ea9c Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 25 Jan 2017 15:31:12 +0100 Subject: [PATCH 123/366] khash: avoid using `kh_put` directly --- src/indexer.c | 4 ++-- src/odb_mempack.c | 2 +- src/offmap.h | 2 ++ src/oidmap.h | 2 ++ src/pack-objects.c | 4 ++-- src/pack.c | 2 +- src/revwalk.c | 2 +- src/sortedcache.c | 2 +- src/strmap.h | 2 ++ src/submodule.c | 2 +- tests/core/oidmap.c | 4 ++-- 11 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/indexer.c b/src/indexer.c index 303dd7cc7..888a06cdb 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -294,7 +294,7 @@ static int store_object(git_indexer *idx) git_oid_cpy(&pentry->sha1, &oid); pentry->offset = entry_start; - k = kh_put(oid, idx->pack->idx_cache, &pentry->sha1, &error); + k = git_oidmap_put(idx->pack->idx_cache, &pentry->sha1, &error); if (error == -1) { git__free(pentry); giterr_set_oom(); @@ -349,7 +349,7 @@ static int save_entry(git_indexer *idx, struct entry *entry, struct git_pack_ent } pentry->offset = entry_start; - k = kh_put(oid, idx->pack->idx_cache, &pentry->sha1, &error); + k = git_oidmap_put(idx->pack->idx_cache, &pentry->sha1, &error); if (error <= 0) { giterr_set(GITERR_INDEXER, "cannot insert object into pack"); diff --git a/src/odb_mempack.c b/src/odb_mempack.c index 3165710b5..da3d85f78 100644 --- a/src/odb_mempack.c +++ b/src/odb_mempack.c @@ -41,7 +41,7 @@ static int impl__write(git_odb_backend *_backend, const git_oid *oid, const void size_t alloc_len; int rval; - pos = kh_put(oid, db->objects, oid, &rval); + pos = git_oidmap_put(db->objects, oid, &rval); if (rval < 0) return -1; diff --git a/src/offmap.h b/src/offmap.h index 4476cf772..1fcd9f68b 100644 --- a/src/offmap.h +++ b/src/offmap.h @@ -38,6 +38,8 @@ typedef khash_t(off) git_offmap; #define git_offmap_set_value_at(h, idx, v) kh_val(h, idx) = v #define git_offmap_delete_at(h, idx) kh_del(off, h, idx) +#define git_offmap_put(h, k, err) kh_put(off, h, k, err) + #define git_offmap_insert(h, key, val, rval) do { \ khiter_t __pos = kh_put(off, h, key, &rval); \ if (rval >= 0) { \ diff --git a/src/oidmap.h b/src/oidmap.h index 8eb8e28c0..c34547aae 100644 --- a/src/oidmap.h +++ b/src/oidmap.h @@ -43,6 +43,8 @@ GIT_INLINE(khint_t) git_oidmap_hash(const git_oid *oid) #define git_oidmap_value_at(h, idx) kh_val(h, idx) #define git_oidmap_delete_at(h, idx) kh_del(oid, h, idx) +#define git_oidmap_put(h, k, err) kh_put(oid, h, k, err) + #define git_oidmap_insert(h, key, val, rval) do { \ khiter_t __pos = kh_put(oid, h, key, &rval); \ if (rval >= 0) { \ diff --git a/src/pack-objects.c b/src/pack-objects.c index 01286fa56..1604744c3 100644 --- a/src/pack-objects.c +++ b/src/pack-objects.c @@ -199,7 +199,7 @@ static void rehash(git_packbuilder *pb) git_oidmap_clear(pb->object_ix); for (i = 0, po = pb->object_list; i < pb->nr_objects; i++, po++) { - pos = kh_put(oid, pb->object_ix, &po->id, &ret); + pos = git_oidmap_put(pb->object_ix, &po->id, &ret); git_oidmap_value_at(pb->object_ix, pos) = po; } } @@ -246,7 +246,7 @@ int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid, git_oid_cpy(&po->id, oid); po->hash = name_hash(name); - pos = kh_put(oid, pb->object_ix, &po->id, &ret); + pos = git_oidmap_put(pb->object_ix, &po->id, &ret); if (ret < 0) { giterr_set_oom(); return ret; diff --git a/src/pack.c b/src/pack.c index fe4a65c53..857d26639 100644 --- a/src/pack.c +++ b/src/pack.c @@ -169,7 +169,7 @@ static int cache_add( while (cache->memory_used + base->len > cache->memory_limit) free_lowest_entry(cache); - k = kh_put(off, cache->entries, offset, &error); + k = git_offmap_put(cache->entries, offset, &error); assert(error != 0); git_oidmap_value_at(cache->entries, k) = entry; cache->memory_used += entry->raw.len; diff --git a/src/revwalk.c b/src/revwalk.c index 32a4ff906..6581d7a37 100644 --- a/src/revwalk.c +++ b/src/revwalk.c @@ -35,7 +35,7 @@ git_commit_list_node *git_revwalk__commit_lookup( git_oid_cpy(&commit->oid, oid); - pos = kh_put(oid, walk->commits, &commit->oid, &ret); + pos = git_oidmap_put(walk->commits, &commit->oid, &ret); assert(ret != 0); git_oidmap_value_at(walk->commits, pos) = commit; diff --git a/src/sortedcache.c b/src/sortedcache.c index 199fa2484..e9e50636b 100644 --- a/src/sortedcache.c +++ b/src/sortedcache.c @@ -294,7 +294,7 @@ int git_sortedcache_upsert(void **out, git_sortedcache *sc, const char *key) item_key = ((char *)item) + sc->item_path_offset; memcpy(item_key, key, keylen); - pos = kh_put(str, sc->map, item_key, &error); + pos = git_strmap_put(sc->map, item_key, &error); if (error < 0) goto done; diff --git a/src/strmap.h b/src/strmap.h index 9fdab95bb..4c5f888ae 100644 --- a/src/strmap.h +++ b/src/strmap.h @@ -42,6 +42,8 @@ typedef khiter_t git_strmap_iter; #define git_strmap_set_value_at(h, idx, v) kh_val(h, idx) = v #define git_strmap_delete_at(h, idx) kh_del(str, h, idx) +#define git_strmap_put(h, k, err) kh_put(str, h, k, err) + #define git_strmap_insert(h, key, val, rval) do { \ khiter_t __pos = kh_put(str, h, key, &rval); \ if (rval >= 0) { \ diff --git a/src/submodule.c b/src/submodule.c index 0bc25cc29..f922518b3 100644 --- a/src/submodule.c +++ b/src/submodule.c @@ -329,7 +329,7 @@ static int submodule_get_or_create(git_submodule **out, git_repository *repo, gi if ((error = submodule_alloc(&sm, repo, name)) < 0) return error; - pos = kh_put(str, map, sm->name, &error); + pos = git_strmap_put(map, sm->name, &error); /* nobody can beat us to adding it */ assert(error != 0); if (error < 0) { diff --git a/tests/core/oidmap.c b/tests/core/oidmap.c index 61d75e9d1..88db692fc 100644 --- a/tests/core/oidmap.c +++ b/tests/core/oidmap.c @@ -36,7 +36,7 @@ void test_core_oidmap__basic(void) pos = git_oidmap_lookup_index(map, &items[i].oid); cl_assert(!git_oidmap_valid_index(map, pos)); - pos = kh_put(oid, map, &items[i].oid, &ret); + pos = git_oidmap_put(map, &items[i].oid, &ret); cl_assert(ret != 0); git_oidmap_value_at(map, pos) = &items[i]; @@ -90,7 +90,7 @@ void test_core_oidmap__hash_collision(void) pos = git_oidmap_lookup_index(map, &items[i].oid); cl_assert(!git_oidmap_valid_index(map, pos)); - pos = kh_put(oid, map, &items[i].oid, &ret); + pos = git_oidmap_put(map, &items[i].oid, &ret); cl_assert(ret != 0); git_oidmap_value_at(map, pos) = &items[i]; From 85d2748c6f75bd810c7376647c8ae32984b5e3bb Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 27 Jan 2017 14:05:10 +0100 Subject: [PATCH 124/366] khash: avoid using `kh_key`/`kh_val` as lvalue --- src/cache.c | 4 ++-- src/indexer.c | 4 ++-- src/odb_mempack.c | 4 ++-- src/oidmap.h | 8 +++++--- src/pack-objects.c | 4 ++-- src/pack.c | 2 +- src/revwalk.c | 2 +- src/sortedcache.c | 4 ++-- src/strmap.h | 1 + tests/core/oidmap.c | 4 ++-- 10 files changed, 20 insertions(+), 17 deletions(-) diff --git a/src/cache.c b/src/cache.c index 965fc0c9b..5f71d16bb 100644 --- a/src/cache.c +++ b/src/cache.c @@ -219,8 +219,8 @@ static void *cache_store(git_cache *cache, git_cached_obj *entry) git_cached_obj_decref(stored_entry); git_cached_obj_incref(entry); - git_oidmap_key(cache->map, pos) = &entry->oid; - git_oidmap_value_at(cache->map, pos) = entry; + git_oidmap_set_key_at(cache->map, pos, &entry->oid); + git_oidmap_set_value_at(cache->map, pos, entry); } else { /* NO OP */ } diff --git a/src/indexer.c b/src/indexer.c index 888a06cdb..3e88bc7ba 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -308,7 +308,7 @@ static int store_object(git_indexer *idx) } - git_oidmap_value_at(idx->pack->idx_cache, k) = pentry; + git_oidmap_set_value_at(idx->pack->idx_cache, k, pentry); git_oid_cpy(&entry->oid, &oid); @@ -356,7 +356,7 @@ static int save_entry(git_indexer *idx, struct entry *entry, struct git_pack_ent return -1; } - git_oidmap_value_at(idx->pack->idx_cache, k) = pentry; + git_oidmap_set_value_at(idx->pack->idx_cache, k, pentry); /* Add the object to the list */ if (git_vector_insert(&idx->objects, entry) < 0) diff --git a/src/odb_mempack.c b/src/odb_mempack.c index da3d85f78..52f8089e1 100644 --- a/src/odb_mempack.c +++ b/src/odb_mempack.c @@ -57,8 +57,8 @@ static int impl__write(git_odb_backend *_backend, const git_oid *oid, const void obj->len = len; obj->type = type; - git_oidmap_key(db->objects, pos) = &obj->oid; - git_oidmap_value_at(db->objects, pos) = obj; + git_oidmap_set_key_at(db->objects, pos, &obj->oid); + git_oidmap_set_value_at(db->objects, pos, obj); if (type == GIT_OBJ_COMMIT) { struct memobject **store = git_array_alloc(db->commits); diff --git a/src/oidmap.h b/src/oidmap.h index c34547aae..e736a516b 100644 --- a/src/oidmap.h +++ b/src/oidmap.h @@ -39,9 +39,11 @@ GIT_INLINE(khint_t) git_oidmap_hash(const git_oid *oid) #define git_oidmap_exists(h, k) (kh_get(oid, h, k) != kh_end(h)) #define git_oidmap_has_data(h, idx) kh_exist(h, idx) -#define git_oidmap_key(h, idx) kh_key(h, idx) -#define git_oidmap_value_at(h, idx) kh_val(h, idx) -#define git_oidmap_delete_at(h, idx) kh_del(oid, h, idx) +#define git_oidmap_key(h, idx) kh_key(h, idx) +#define git_oidmap_set_key_at(h, idx, k) kh_key(h, idx) = k +#define git_oidmap_value_at(h, idx) kh_val(h, idx) +#define git_oidmap_set_value_at(h, idx, v) kh_val(h, idx) = v +#define git_oidmap_delete_at(h, idx) kh_del(oid, h, idx) #define git_oidmap_put(h, k, err) kh_put(oid, h, k, err) diff --git a/src/pack-objects.c b/src/pack-objects.c index 1604744c3..fa11763c2 100644 --- a/src/pack-objects.c +++ b/src/pack-objects.c @@ -200,7 +200,7 @@ static void rehash(git_packbuilder *pb) git_oidmap_clear(pb->object_ix); for (i = 0, po = pb->object_list; i < pb->nr_objects; i++, po++) { pos = git_oidmap_put(pb->object_ix, &po->id, &ret); - git_oidmap_value_at(pb->object_ix, pos) = po; + git_oidmap_set_value_at(pb->object_ix, pos, po); } } @@ -252,7 +252,7 @@ int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid, return ret; } assert(ret != 0); - git_oidmap_value_at(pb->object_ix, pos) = po; + git_oidmap_set_value_at(pb->object_ix, pos, po); pb->done = false; diff --git a/src/pack.c b/src/pack.c index 857d26639..4e30ca7c3 100644 --- a/src/pack.c +++ b/src/pack.c @@ -171,7 +171,7 @@ static int cache_add( k = git_offmap_put(cache->entries, offset, &error); assert(error != 0); - git_oidmap_value_at(cache->entries, k) = entry; + git_offmap_set_value_at(cache->entries, k, entry); cache->memory_used += entry->raw.len; *cached_out = entry; diff --git a/src/revwalk.c b/src/revwalk.c index 6581d7a37..ac5400253 100644 --- a/src/revwalk.c +++ b/src/revwalk.c @@ -37,7 +37,7 @@ git_commit_list_node *git_revwalk__commit_lookup( pos = git_oidmap_put(walk->commits, &commit->oid, &ret); assert(ret != 0); - git_oidmap_value_at(walk->commits, pos) = commit; + git_oidmap_set_value_at(walk->commits, pos, commit); return commit; } diff --git a/src/sortedcache.c b/src/sortedcache.c index e9e50636b..20e137e91 100644 --- a/src/sortedcache.c +++ b/src/sortedcache.c @@ -299,8 +299,8 @@ int git_sortedcache_upsert(void **out, git_sortedcache *sc, const char *key) goto done; if (!error) - git_strmap_key(sc->map, pos) = item_key; - git_strmap_value_at(sc->map, pos) = item; + git_strmap_set_key_at(sc->map, pos, item_key); + git_strmap_set_value_at(sc->map, pos, item); error = git_vector_insert(&sc->items, item); if (error < 0) diff --git a/src/strmap.h b/src/strmap.h index 4c5f888ae..7b9695695 100644 --- a/src/strmap.h +++ b/src/strmap.h @@ -38,6 +38,7 @@ typedef khiter_t git_strmap_iter; #define git_strmap_has_data(h, idx) kh_exist(h, idx) #define git_strmap_key(h, idx) kh_key(h, idx) +#define git_strmap_set_key_at(h, idx, k) kh_val(h, idx) = k #define git_strmap_value_at(h, idx) kh_val(h, idx) #define git_strmap_set_value_at(h, idx, v) kh_val(h, idx) = v #define git_strmap_delete_at(h, idx) kh_del(str, h, idx) diff --git a/tests/core/oidmap.c b/tests/core/oidmap.c index 88db692fc..92b8c1937 100644 --- a/tests/core/oidmap.c +++ b/tests/core/oidmap.c @@ -39,7 +39,7 @@ void test_core_oidmap__basic(void) pos = git_oidmap_put(map, &items[i].oid, &ret); cl_assert(ret != 0); - git_oidmap_value_at(map, pos) = &items[i]; + git_oidmap_set_value_at(map, pos, &items[i]); } @@ -93,7 +93,7 @@ void test_core_oidmap__hash_collision(void) pos = git_oidmap_put(map, &items[i].oid, &ret); cl_assert(ret != 0); - git_oidmap_value_at(map, pos) = &items[i]; + git_oidmap_set_value_at(map, pos, &items[i]); } From 73028af85c11bd947184a73c1e2d7902819695b2 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 27 Jan 2017 14:20:24 +0100 Subject: [PATCH 125/366] khash: avoid using macro magic to get return address --- src/attr.c | 2 +- src/attrcache.c | 4 ++-- src/cache.c | 2 +- src/config_file.c | 2 +- src/describe.c | 2 +- src/diff_driver.c | 4 ++-- src/fileops.c | 2 +- src/idxmap.h | 12 ++++++------ src/index.c | 10 +++++----- src/mwindow.c | 2 +- src/offmap.h | 6 +++--- src/oidmap.h | 6 +++--- src/pack-objects.c | 2 +- src/strmap.h | 6 +++--- src/submodule.c | 4 ++-- src/transaction.c | 2 +- src/tree.c | 4 ++-- tests/core/strmap.c | 2 +- 18 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/attr.c b/src/attr.c index 93dea123f..4023526e5 100644 --- a/src/attr.c +++ b/src/attr.c @@ -209,7 +209,7 @@ int git_attr_foreach( if (git_strmap_exists(seen, assign->name)) continue; - git_strmap_insert(seen, assign->name, assign, error); + git_strmap_insert(seen, assign->name, assign, &error); if (error < 0) goto cleanup; diff --git a/src/attrcache.c b/src/attrcache.c index cf0707ef0..8860d77b1 100644 --- a/src/attrcache.c +++ b/src/attrcache.c @@ -82,7 +82,7 @@ static int attr_cache_make_entry( &entry, git_repository_workdir(repo), path, &cache->pool); if (!error) { - git_strmap_insert(cache->files, entry->path, entry, error); + git_strmap_insert(cache->files, entry->path, entry, &error); if (error > 0) error = 0; } @@ -435,7 +435,7 @@ int git_attr_cache__insert_macro(git_repository *repo, git_attr_rule *macro) giterr_set(GITERR_OS, "unable to get attr cache lock"); error = -1; } else { - git_strmap_insert(macros, macro->match.pattern, macro, error); + git_strmap_insert(macros, macro->match.pattern, macro, &error); git_mutex_unlock(&cache->lock); } diff --git a/src/cache.c b/src/cache.c index 5f71d16bb..f76e72d93 100644 --- a/src/cache.c +++ b/src/cache.c @@ -199,7 +199,7 @@ static void *cache_store(git_cache *cache, git_cached_obj *entry) if (!git_oidmap_valid_index(cache->map, pos)) { int rval; - git_oidmap_insert(cache->map, &entry->oid, entry, rval); + git_oidmap_insert(cache->map, &entry->oid, entry, &rval); if (rval >= 0) { git_cached_obj_incref(entry); cache->used_memory += entry->size; diff --git a/src/config_file.c b/src/config_file.c index 2e3d568bb..6a3738905 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -179,7 +179,7 @@ static int append_entry(git_strmap *values, cvar_t *var) pos = git_strmap_lookup_index(values, var->entry->name); if (!git_strmap_valid_index(values, pos)) { - git_strmap_insert(values, var->entry->name, var, error); + git_strmap_insert(values, var->entry->name, var, &error); } else { existing = git_strmap_value_at(values, pos); while (existing->next != NULL) { diff --git a/src/describe.c b/src/describe.c index 16e195542..152385836 100644 --- a/src/describe.c +++ b/src/describe.c @@ -127,7 +127,7 @@ static int add_to_known_names( if (!found) { int ret; - git_oidmap_insert(names, &e->peeled, e, ret); + git_oidmap_insert(names, &e->peeled, e, &ret); if (ret < 0) return -1; } diff --git a/src/diff_driver.c b/src/diff_driver.c index 0adf704fb..721388bb9 100644 --- a/src/diff_driver.c +++ b/src/diff_driver.c @@ -217,7 +217,7 @@ static int git_diff_driver_builtin( goto done; } - git_strmap_insert(reg->drivers, drv->name, drv, error); + git_strmap_insert(reg->drivers, drv->name, drv, &error); if (error > 0) error = 0; @@ -331,7 +331,7 @@ static int git_diff_driver_load( goto done; /* store driver in registry */ - git_strmap_insert(reg->drivers, drv->name, drv, error); + git_strmap_insert(reg->drivers, drv->name, drv, &error); if (error < 0) goto done; error = 0; diff --git a/src/fileops.c b/src/fileops.c index 7a8733209..0b0ed42be 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -607,7 +607,7 @@ retry_lstat: memcpy(cache_path, make_path.ptr, make_path.size + 1); - git_strmap_insert(opts->dir_map, cache_path, cache_path, error); + git_strmap_insert(opts->dir_map, cache_path, cache_path, &error); if (error < 0) goto done; } diff --git a/src/idxmap.h b/src/idxmap.h index 4122a89fe..e8fd3631a 100644 --- a/src/idxmap.h +++ b/src/idxmap.h @@ -51,16 +51,16 @@ static kh_inline khint_t idxentry_hash(const git_index_entry *e) ((*(hp) = kh_init(idxicase)) == NULL) ? giterr_set_oom(), -1 : 0 #define git_idxmap_insert(h, key, val, rval) do { \ - khiter_t __pos = kh_put(idx, h, key, &rval); \ - if (rval >= 0) { \ - if (rval == 0) kh_key(h, __pos) = key; \ + khiter_t __pos = kh_put(idx, h, key, rval); \ + if ((*rval) >= 0) { \ + if ((*rval) == 0) kh_key(h, __pos) = key; \ kh_val(h, __pos) = val; \ } } while (0) #define git_idxmap_icase_insert(h, key, val, rval) do { \ - khiter_t __pos = kh_put(idxicase, h, key, &rval); \ - if (rval >= 0) { \ - if (rval == 0) kh_key(h, __pos) = key; \ + khiter_t __pos = kh_put(idxicase, h, key, rval); \ + if ((*rval) >= 0) { \ + if ((*rval) == 0) kh_key(h, __pos) = key; \ kh_val(h, __pos) = val; \ } } while (0) diff --git a/src/index.c b/src/index.c index f27fa16d2..d7deae544 100644 --- a/src/index.c +++ b/src/index.c @@ -1365,7 +1365,7 @@ static int index_insert( error = git_vector_insert_sorted(&index->entries, entry, index_no_dups); if (error == 0) { - INSERT_IN_MAP(index, entry, error); + INSERT_IN_MAP(index, entry, &error); } } @@ -1592,7 +1592,7 @@ int git_index__fill(git_index *index, const git_vector *source_entries) if ((ret = git_vector_insert(&index->entries, entry)) < 0) break; - INSERT_IN_MAP(index, entry, ret); + INSERT_IN_MAP(index, entry, &ret); if (ret < 0) break; } @@ -2499,7 +2499,7 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size) goto done; } - INSERT_IN_MAP(index, entry, error); + INSERT_IN_MAP(index, entry, &error); if (error < 0) { index_entry_free(entry); @@ -2984,7 +2984,7 @@ int git_index_read_tree(git_index *index, const git_tree *tree) kh_resize(idx, entries_map, entries.length); git_vector_foreach(&entries, i, e) { - INSERT_IN_MAP_EX(index, entries_map, e, error); + INSERT_IN_MAP_EX(index, entries_map, e, &error); if (error < 0) { giterr_set(GITERR_INDEX, "failed to insert entry into map"); @@ -3103,7 +3103,7 @@ static int git_index_read_iterator( if (add_entry) { if ((error = git_vector_insert(&new_entries, add_entry)) == 0) - INSERT_IN_MAP_EX(index, new_entries_map, add_entry, error); + INSERT_IN_MAP_EX(index, new_entries_map, add_entry, &error); } if (remove_entry && error >= 0) diff --git a/src/mwindow.c b/src/mwindow.c index 520e7685f..91dbcae7f 100644 --- a/src/mwindow.c +++ b/src/mwindow.c @@ -84,7 +84,7 @@ int git_mwindow_get_pack(struct git_pack_file **out, const char *path) git_atomic_inc(&pack->refcount); - git_strmap_insert(git__pack_cache, pack->pack_name, pack, error); + git_strmap_insert(git__pack_cache, pack->pack_name, pack, &error); git_mutex_unlock(&git__mwindow_mutex); if (error < 0) { diff --git a/src/offmap.h b/src/offmap.h index 1fcd9f68b..56003cf62 100644 --- a/src/offmap.h +++ b/src/offmap.h @@ -41,9 +41,9 @@ typedef khash_t(off) git_offmap; #define git_offmap_put(h, k, err) kh_put(off, h, k, err) #define git_offmap_insert(h, key, val, rval) do { \ - khiter_t __pos = kh_put(off, h, key, &rval); \ - if (rval >= 0) { \ - if (rval == 0) kh_key(h, __pos) = key; \ + khiter_t __pos = kh_put(off, h, key, rval); \ + if ((*rval) >= 0) { \ + if ((*rval) == 0) kh_key(h, __pos) = key; \ kh_val(h, __pos) = val; \ } } while (0) diff --git a/src/oidmap.h b/src/oidmap.h index e736a516b..0a144361a 100644 --- a/src/oidmap.h +++ b/src/oidmap.h @@ -48,9 +48,9 @@ GIT_INLINE(khint_t) git_oidmap_hash(const git_oid *oid) #define git_oidmap_put(h, k, err) kh_put(oid, h, k, err) #define git_oidmap_insert(h, key, val, rval) do { \ - khiter_t __pos = kh_put(oid, h, key, &rval); \ - if (rval >= 0) { \ - if (rval == 0) kh_key(h, __pos) = key; \ + khiter_t __pos = kh_put(oid, h, key, rval); \ + if ((*rval) >= 0) { \ + if ((*rval) == 0) kh_key(h, __pos) = key; \ kh_val(h, __pos) = val; \ } } while (0) diff --git a/src/pack-objects.c b/src/pack-objects.c index fa11763c2..1b4ec9d15 100644 --- a/src/pack-objects.c +++ b/src/pack-objects.c @@ -1540,7 +1540,7 @@ static int retrieve_object(git_walk_object **out, git_packbuilder *pb, const git if ((error = lookup_walk_object(&obj, pb, id)) < 0) return error; - git_oidmap_insert(pb->walk_objects, &obj->id, obj, error); + git_oidmap_insert(pb->walk_objects, &obj->id, obj, &error); } *out = obj; diff --git a/src/strmap.h b/src/strmap.h index 7b9695695..b92631082 100644 --- a/src/strmap.h +++ b/src/strmap.h @@ -46,9 +46,9 @@ typedef khiter_t git_strmap_iter; #define git_strmap_put(h, k, err) kh_put(str, h, k, err) #define git_strmap_insert(h, key, val, rval) do { \ - khiter_t __pos = kh_put(str, h, key, &rval); \ - if (rval >= 0) { \ - if (rval == 0) kh_key(h, __pos) = key; \ + khiter_t __pos = kh_put(str, h, key, rval); \ + if ((*rval) >= 0) { \ + if ((*rval) == 0) kh_key(h, __pos) = key; \ kh_val(h, __pos) = val; \ } } while (0) diff --git a/src/submodule.c b/src/submodule.c index f922518b3..095bbb090 100644 --- a/src/submodule.c +++ b/src/submodule.c @@ -186,7 +186,7 @@ static int load_submodule_names(git_strmap *out, git_config *cfg) ldot = strrchr(entry->name, '.'); git_buf_put(&buf, fdot + 1, ldot - fdot - 1); - git_strmap_insert(out, entry->value, git_buf_detach(&buf), rval); + git_strmap_insert(out, entry->value, git_buf_detach(&buf), &rval); if (rval < 0) { giterr_set(GITERR_NOMEMORY, "error inserting submodule into hash table"); return -1; @@ -1866,7 +1866,7 @@ static int submodule_load_each(const git_config_entry *entry, void *payload) goto done; } - git_strmap_insert(map, sm->name, sm, error); + git_strmap_insert(map, sm->name, sm, &error); assert(error != 0); if (error < 0) goto done; diff --git a/src/transaction.c b/src/transaction.c index ffe374a86..5b345e1a9 100644 --- a/src/transaction.c +++ b/src/transaction.c @@ -120,7 +120,7 @@ int git_transaction_lock_ref(git_transaction *tx, const char *refname) if ((error = git_refdb_lock(&node->payload, tx->db, refname)) < 0) return error; - git_strmap_insert(tx->locks, node->name, node, error); + git_strmap_insert(tx->locks, node->name, node, &error); if (error < 0) goto cleanup; diff --git a/src/tree.c b/src/tree.c index 26da296d5..8f4cab814 100644 --- a/src/tree.c +++ b/src/tree.c @@ -505,7 +505,7 @@ static int append_entry( entry->attr = (uint16_t)filemode; - git_strmap_insert(bld->map, entry->filename, entry, error); + 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); @@ -754,7 +754,7 @@ int git_treebuilder_insert( entry = alloc_entry(filename, strlen(filename), id); GITERR_CHECK_ALLOC(entry); - git_strmap_insert(bld->map, entry->filename, entry, error); + git_strmap_insert(bld->map, entry->filename, entry, &error); if (error < 0) { git_tree_entry_free(entry); diff --git a/tests/core/strmap.c b/tests/core/strmap.c index 3b4276aea..860f1109b 100644 --- a/tests/core/strmap.c +++ b/tests/core/strmap.c @@ -36,7 +36,7 @@ static void insert_strings(git_strmap *table, int count) for (j = 0, over = i / 26; over > 0; j++, over = over / 26) str[j] = 'A' + (over % 26); - git_strmap_insert(table, str, str, err); + git_strmap_insert(table, str, str, &err); cl_assert(err >= 0); } From f14f75d4a1e656ac8df3fb6a512cc4a157641d8b Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Thu, 2 Feb 2017 13:08:52 +0100 Subject: [PATCH 126/366] khash: avoid using `kh_resize` directly --- src/idxmap.h | 1 + src/index.c | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/idxmap.h b/src/idxmap.h index e8fd3631a..21de5af78 100644 --- a/src/idxmap.h +++ b/src/idxmap.h @@ -71,6 +71,7 @@ static kh_inline khint_t idxentry_hash(const git_index_entry *e) #define git_idxmap_has_data(h, idx) kh_exist(h, idx) #define git_idxmap_resize(h,s) kh_resize(idx, h, s) +#define git_idxmap_icase_resize(h,s) kh_resize(idxicase, h, s) #define git_idxmap_free(h) kh_destroy(idx, h), h = NULL #define git_idxmap_clear(h) kh_clear(idx, h) diff --git a/src/index.c b/src/index.c index d7deae544..7b510e04e 100644 --- a/src/index.c +++ b/src/index.c @@ -2479,9 +2479,9 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size) assert(!index->entries.length); if (index->ignore_case) - kh_resize(idxicase, (khash_t(idxicase) *) index->entries_map, header.entry_count); + git_idxmap_icase_resize((khash_t(idxicase) *) index->entries_map, header.entry_count); else - kh_resize(idx, index->entries_map, header.entry_count); + git_idxmap_resize(index->entries_map, header.entry_count); /* Parse all the entries */ for (i = 0; i < header.entry_count && buffer_size > INDEX_FOOTER_SIZE; ++i) { @@ -2979,9 +2979,9 @@ int git_index_read_tree(git_index *index, const git_tree *tree) goto cleanup; if (index->ignore_case) - kh_resize(idxicase, (khash_t(idxicase) *) entries_map, entries.length); + git_idxmap_icase_resize((khash_t(idxicase) *) entries_map, entries.length); else - kh_resize(idx, entries_map, entries.length); + git_idxmap_resize(entries_map, entries.length); git_vector_foreach(&entries, i, e) { INSERT_IN_MAP_EX(index, entries_map, e, &error); @@ -3037,9 +3037,9 @@ static int git_index_read_iterator( goto done; if (index->ignore_case && new_length_hint) - kh_resize(idxicase, (khash_t(idxicase) *) new_entries_map, new_length_hint); + git_idxmap_icase_resize((khash_t(idxicase) *) new_entries_map, new_length_hint); else if (new_length_hint) - kh_resize(idx, new_entries_map, new_length_hint); + git_idxmap_resize(new_entries_map, new_length_hint); opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE | GIT_ITERATOR_INCLUDE_CONFLICTS; From a13cfd2af2aa2f9be660fc1c789405b5188b904d Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 27 Jan 2017 14:13:49 +0100 Subject: [PATCH 127/366] strmap: convert macros to functions --- src/strmap.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/strmap.h | 44 ++++++++++-------------- 2 files changed, 112 insertions(+), 27 deletions(-) diff --git a/src/strmap.c b/src/strmap.c index b26a13d1f..09ace0fce 100644 --- a/src/strmap.c +++ b/src/strmap.c @@ -7,6 +7,101 @@ #include "strmap.h" +GIT__USE_STRMAP + +int git_strmap_alloc(git_strmap **map) +{ + if ((*map = kh_init(str)) == NULL) { + giterr_set_oom(); + return -1; + } + + return 0; +} + +void git_strmap__free(git_strmap *map) +{ + kh_destroy(str, map); +} + +void git_strmap_clear(git_strmap *map) +{ + kh_clear(str, map); +} + +size_t git_strmap_num_entries(git_strmap *map) +{ + return kh_size(map); +} + +size_t git_strmap_lookup_index(git_strmap *map, const char *key) +{ + return kh_get(str, map, key); +} + +int git_strmap_valid_index(git_strmap *map, size_t idx) +{ + return idx != kh_end(map); +} + +int git_strmap_exists(git_strmap *map, const char *key) +{ + return kh_get(str, map, key) != kh_end(map); +} + +int git_strmap_has_data(git_strmap *map, size_t idx) +{ + return kh_exist(map, idx); +} + +const char *git_strmap_key(git_strmap *map, size_t idx) +{ + return kh_key(map, idx); +} + +void git_strmap_set_key_at(git_strmap *map, size_t idx, char *key) +{ + kh_val(map, idx) = key; +} + +void *git_strmap_value_at(git_strmap *map, size_t idx) +{ + return kh_val(map, idx); +} + +void git_strmap_set_value_at(git_strmap *map, size_t idx, void *value) +{ + kh_val(map, idx) = value; +} + +void git_strmap_delete_at(git_strmap *map, size_t idx) +{ + kh_del(str, map, idx); +} + +int git_strmap_put(git_strmap *map, const char *key, int *err) +{ + return kh_put(str, map, key, err); +} + +void git_strmap_insert(git_strmap *map, const char *key, void *value, int *rval) +{ + khiter_t idx = kh_put(str, map, key, rval); + + if ((*rval) >= 0) { + if ((*rval) == 0) + kh_key(map, idx) = key; + kh_val(map, idx) = value; + } +} + +void git_strmap_delete(git_strmap *map, const char *key) +{ + khiter_t idx = git_strmap_lookup_index(map, key); + if (git_strmap_valid_index(map, idx)) + git_strmap_delete_at(map, idx); +} + int git_strmap_next( void **data, git_strmap_iter* iter, diff --git a/src/strmap.h b/src/strmap.h index b92631082..2c898e00b 100644 --- a/src/strmap.h +++ b/src/strmap.h @@ -23,39 +23,29 @@ typedef khiter_t git_strmap_iter; #define GIT__USE_STRMAP \ __KHASH_IMPL(str, static kh_inline, const char *, void *, 1, kh_str_hash_func, kh_str_hash_equal) -#define git_strmap_alloc(hp) \ - ((*(hp) = kh_init(str)) == NULL) ? giterr_set_oom(), -1 : 0 +int git_strmap_alloc(git_strmap **map); -#define git_strmap_free(h) kh_destroy(str, h), h = NULL -#define git_strmap_clear(h) kh_clear(str, h) +#define git_strmap_free(h) git_strmap__free(h); (h) = NULL +void git_strmap__free(git_strmap *map); +void git_strmap_clear(git_strmap *map); -#define git_strmap_num_entries(h) kh_size(h) +size_t git_strmap_num_entries(git_strmap *map); -#define git_strmap_lookup_index(h, k) kh_get(str, h, k) -#define git_strmap_valid_index(h, idx) (idx != kh_end(h)) +size_t git_strmap_lookup_index(git_strmap *map, const char *key); +int git_strmap_valid_index(git_strmap *map, size_t idx); -#define git_strmap_exists(h, k) (kh_get(str, h, k) != kh_end(h)) -#define git_strmap_has_data(h, idx) kh_exist(h, idx) +int git_strmap_exists(git_strmap *map, const char *key); +int git_strmap_has_data(git_strmap *map, size_t idx); -#define git_strmap_key(h, idx) kh_key(h, idx) -#define git_strmap_set_key_at(h, idx, k) kh_val(h, idx) = k -#define git_strmap_value_at(h, idx) kh_val(h, idx) -#define git_strmap_set_value_at(h, idx, v) kh_val(h, idx) = v -#define git_strmap_delete_at(h, idx) kh_del(str, h, idx) +const char *git_strmap_key(git_strmap *map, size_t idx); +void git_strmap_set_key_at(git_strmap *map, size_t idx, char *key); +void *git_strmap_value_at(git_strmap *map, size_t idx); +void git_strmap_set_value_at(git_strmap *map, size_t idx, void *value); +void git_strmap_delete_at(git_strmap *map, size_t idx); -#define git_strmap_put(h, k, err) kh_put(str, h, k, err) - -#define git_strmap_insert(h, key, val, rval) do { \ - khiter_t __pos = kh_put(str, h, key, rval); \ - if ((*rval) >= 0) { \ - if ((*rval) == 0) kh_key(h, __pos) = key; \ - kh_val(h, __pos) = val; \ - } } while (0) - -#define git_strmap_delete(h, key) do { \ - khiter_t __pos = git_strmap_lookup_index(h, key); \ - if (git_strmap_valid_index(h, __pos)) \ - git_strmap_delete_at(h, __pos); } while (0) +int git_strmap_put(git_strmap *map, const char *key, int *err); +void git_strmap_insert(git_strmap *map, const char *key, void *value, int *rval); +void git_strmap_delete(git_strmap *map, const char *key); #define git_strmap_foreach kh_foreach #define git_strmap_foreach_value kh_foreach_value From 13c3bc9adf7c3e467c6d1a577859bf31d551022b Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 27 Jan 2017 14:32:23 +0100 Subject: [PATCH 128/366] strmap: remove GIT__USE_STRMAP macro --- src/attr.c | 2 -- src/attrcache.c | 2 -- src/checkout.c | 2 -- src/config_file.c | 2 -- src/diff_driver.c | 2 -- src/fileops.c | 2 -- src/mwindow.c | 2 -- src/refdb_fs.c | 2 -- src/refs.c | 2 -- src/repository.c | 1 - src/sortedcache.c | 2 -- src/strmap.c | 2 +- src/strmap.h | 3 --- src/transaction.c | 2 -- src/tree.c | 2 -- tests/core/strmap.c | 2 -- 16 files changed, 1 insertion(+), 31 deletions(-) diff --git a/src/attr.c b/src/attr.c index 4023526e5..999f41318 100644 --- a/src/attr.c +++ b/src/attr.c @@ -7,8 +7,6 @@ #include "git2/oid.h" #include -GIT__USE_STRMAP - const char *git_attr__true = "[internal]__TRUE__"; const char *git_attr__false = "[internal]__FALSE__"; const char *git_attr__unset = "[internal]__UNSET__"; diff --git a/src/attrcache.c b/src/attrcache.c index 8860d77b1..6cac14bc3 100644 --- a/src/attrcache.c +++ b/src/attrcache.c @@ -5,8 +5,6 @@ #include "sysdir.h" #include "ignore.h" -GIT__USE_STRMAP - GIT_INLINE(int) attr_cache_lock(git_attr_cache *cache) { GIT_UNUSED(cache); /* avoid warning if threading is off */ diff --git a/src/checkout.c b/src/checkout.c index b70d5ab35..af600da6c 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -35,8 +35,6 @@ #include "pool.h" #include "strmap.h" -GIT__USE_STRMAP - /* See docs/checkout-internals.md for more information */ enum { diff --git a/src/config_file.c b/src/config_file.c index 6a3738905..cd5727c05 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -21,8 +21,6 @@ #include #include -GIT__USE_STRMAP - typedef struct cvar_t { struct cvar_t *next; git_config_entry *entry; diff --git a/src/diff_driver.c b/src/diff_driver.c index 721388bb9..9109f3155 100644 --- a/src/diff_driver.c +++ b/src/diff_driver.c @@ -16,8 +16,6 @@ #include "config.h" #include "repository.h" -GIT__USE_STRMAP - typedef enum { DIFF_DRIVER_AUTO = 0, DIFF_DRIVER_BINARY = 1, diff --git a/src/fileops.c b/src/fileops.c index 0b0ed42be..57dea8fce 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -13,8 +13,6 @@ #include "win32/findfile.h" #endif -GIT__USE_STRMAP - int git_futils_mkpath2file(const char *file_path, const mode_t mode) { return git_futils_mkdir( diff --git a/src/mwindow.c b/src/mwindow.c index 91dbcae7f..7bb9dbbe2 100644 --- a/src/mwindow.c +++ b/src/mwindow.c @@ -14,8 +14,6 @@ #include "strmap.h" #include "pack.h" -GIT__USE_STRMAP - #define DEFAULT_WINDOW_SIZE \ (sizeof(void*) >= 8 \ ? 1 * 1024 * 1024 * 1024 \ diff --git a/src/refdb_fs.c b/src/refdb_fs.c index def5302de..e2a69d6ed 100644 --- a/src/refdb_fs.c +++ b/src/refdb_fs.c @@ -26,8 +26,6 @@ #include #include -GIT__USE_STRMAP - #define DEFAULT_NESTING_LEVEL 5 #define MAX_NESTING_LEVEL 10 diff --git a/src/refs.c b/src/refs.c index 140b175af..70f5519c6 100644 --- a/src/refs.c +++ b/src/refs.c @@ -26,8 +26,6 @@ bool git_reference__enable_symbolic_ref_target_validation = true; -GIT__USE_STRMAP - #define DEFAULT_NESTING_LEVEL 5 #define MAX_NESTING_LEVEL 10 diff --git a/src/repository.c b/src/repository.c index 4b937be20..0db481638 100644 --- a/src/repository.c +++ b/src/repository.c @@ -30,7 +30,6 @@ #include "submodule.h" #include "worktree.h" -GIT__USE_STRMAP #include "strmap.h" #ifdef GIT_WIN32 diff --git a/src/sortedcache.c b/src/sortedcache.c index 20e137e91..cc322d478 100644 --- a/src/sortedcache.c +++ b/src/sortedcache.c @@ -1,7 +1,5 @@ #include "sortedcache.h" -GIT__USE_STRMAP - int git_sortedcache_new( git_sortedcache **out, size_t item_path_offset, diff --git a/src/strmap.c b/src/strmap.c index 09ace0fce..678d98344 100644 --- a/src/strmap.c +++ b/src/strmap.c @@ -7,7 +7,7 @@ #include "strmap.h" -GIT__USE_STRMAP +__KHASH_IMPL(str, static kh_inline, const char *, void *, 1, kh_str_hash_func, kh_str_hash_equal) int git_strmap_alloc(git_strmap **map) { diff --git a/src/strmap.h b/src/strmap.h index 2c898e00b..389702c9b 100644 --- a/src/strmap.h +++ b/src/strmap.h @@ -20,9 +20,6 @@ __KHASH_TYPE(str, const char *, void *) typedef khash_t(str) git_strmap; typedef khiter_t git_strmap_iter; -#define GIT__USE_STRMAP \ - __KHASH_IMPL(str, static kh_inline, const char *, void *, 1, kh_str_hash_func, kh_str_hash_equal) - int git_strmap_alloc(git_strmap **map); #define git_strmap_free(h) git_strmap__free(h); (h) = NULL diff --git a/src/transaction.c b/src/transaction.c index 5b345e1a9..3d3f35a03 100644 --- a/src/transaction.c +++ b/src/transaction.c @@ -19,8 +19,6 @@ #include "git2/sys/refs.h" #include "git2/sys/refdb_backend.h" -GIT__USE_STRMAP - typedef enum { TRANSACTION_NONE, TRANSACTION_REFS, diff --git a/src/tree.c b/src/tree.c index 8f4cab814..dba2060c3 100644 --- a/src/tree.c +++ b/src/tree.c @@ -20,8 +20,6 @@ #define TREE_ENTRY_CHECK_NAMELEN(n) \ if (n > UINT16_MAX) { giterr_set(GITERR_INVALID, "tree entry path too long"); } -GIT__USE_STRMAP - static bool valid_filemode(const int filemode) { return (filemode == GIT_FILEMODE_TREE diff --git a/tests/core/strmap.c b/tests/core/strmap.c index 860f1109b..2fa594d43 100644 --- a/tests/core/strmap.c +++ b/tests/core/strmap.c @@ -1,8 +1,6 @@ #include "clar_libgit2.h" #include "strmap.h" -GIT__USE_STRMAP - git_strmap *g_table; void test_core_strmap__initialize(void) From 659f5d07d50d782d1c2ded8eb7b1f02a32117fd9 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 27 Jan 2017 14:53:23 +0100 Subject: [PATCH 129/366] oidmap: convert macros to functions --- src/oidmap.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/oidmap.h | 39 +++++++++------------ 2 files changed, 115 insertions(+), 22 deletions(-) create mode 100644 src/oidmap.c diff --git a/src/oidmap.c b/src/oidmap.c new file mode 100644 index 000000000..ab821df8d --- /dev/null +++ b/src/oidmap.c @@ -0,0 +1,98 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#include "oidmap.h" + +__KHASH_IMPL(oid, static kh_inline, const git_oid *, void *, 1, git_oidmap_hash, git_oid_equal) + +git_oidmap *git_oidmap_alloc() +{ + return kh_init(oid); +} + +void git_oidmap__free(git_oidmap *map) +{ + kh_destroy(oid, map); +} + +void git_oidmap_clear(git_oidmap *map) +{ + kh_clear(oid, map); +} + +size_t git_oidmap_size(git_oidmap *map) +{ + return kh_size(map); +} + +size_t git_oidmap_lookup_index(git_oidmap *map, const git_oid *key) +{ + return kh_get(oid, map, key); +} + +int git_oidmap_valid_index(git_oidmap *map, size_t idx) +{ + return idx != kh_end(map); +} + +int git_oidmap_exists(git_oidmap *map, const git_oid *key) +{ + return kh_get(oid, map, key) != kh_end(map); +} + +int git_oidmap_has_data(git_oidmap *map, size_t idx) +{ + return kh_exist(map, idx); +} + +const git_oid *git_oidmap_key(git_oidmap *map, size_t idx) +{ + return kh_key(map, idx); +} + +void git_oidmap_set_key_at(git_oidmap *map, size_t idx, git_oid *key) +{ + kh_key(map, idx) = key; +} + +void *git_oidmap_value_at(git_oidmap *map, size_t idx) +{ + return kh_val(map, idx); +} + +void git_oidmap_set_value_at(git_oidmap *map, size_t idx, void *value) +{ + kh_val(map, idx) = value; +} + +void git_oidmap_delete_at(git_oidmap *map, size_t idx) +{ + kh_del(oid, map, idx); +} + +int git_oidmap_put(git_oidmap *map, const git_oid *key, int *err) +{ + return kh_put(oid, map, key, err); +} + +void git_oidmap_insert(git_oidmap *map, const git_oid *key, void *value, int *rval) +{ + khiter_t idx = kh_put(oid, map, key, rval); + + if ((*rval) >= 0) { + if ((*rval) == 0) + kh_key(map, idx) = key; + kh_val(map, idx) = value; + } +} + +void git_oidmap_delete(git_oidmap *map, const git_oid *key) +{ + khiter_t idx = git_oidmap_lookup_index(map, key); + if (git_oidmap_valid_index(map, idx)) + git_oidmap_delete_at(map, idx); +} diff --git a/src/oidmap.h b/src/oidmap.h index 0a144361a..bfad8e2ad 100644 --- a/src/oidmap.h +++ b/src/oidmap.h @@ -30,37 +30,32 @@ GIT_INLINE(khint_t) git_oidmap_hash(const git_oid *oid) #define GIT__USE_OIDMAP \ __KHASH_IMPL(oid, static kh_inline, const git_oid *, void *, 1, git_oidmap_hash, git_oid_equal) -#define git_oidmap_alloc() kh_init(oid) -#define git_oidmap_free(h) kh_destroy(oid,h), h = NULL +git_oidmap *git_oidmap_alloc(void); +#define git_oidmap_free(h) git_oidmap__free(h); (h) = NULL +void git_oidmap__free(git_oidmap *map); +void git_oidmap_clear(git_oidmap *map); -#define git_oidmap_lookup_index(h, k) kh_get(oid, h, k) -#define git_oidmap_valid_index(h, idx) (idx != kh_end(h)) +size_t git_oidmap_size(git_oidmap *map); -#define git_oidmap_exists(h, k) (kh_get(oid, h, k) != kh_end(h)) -#define git_oidmap_has_data(h, idx) kh_exist(h, idx) +size_t git_oidmap_lookup_index(git_oidmap *map, const git_oid *key); +int git_oidmap_valid_index(git_oidmap *map, size_t idx); -#define git_oidmap_key(h, idx) kh_key(h, idx) -#define git_oidmap_set_key_at(h, idx, k) kh_key(h, idx) = k -#define git_oidmap_value_at(h, idx) kh_val(h, idx) -#define git_oidmap_set_value_at(h, idx, v) kh_val(h, idx) = v -#define git_oidmap_delete_at(h, idx) kh_del(oid, h, idx) +int git_oidmap_exists(git_oidmap *map, const git_oid *key); +int git_oidmap_has_data(git_oidmap *map, size_t idx); -#define git_oidmap_put(h, k, err) kh_put(oid, h, k, err) +const git_oid *git_oidmap_key(git_oidmap *map, size_t idx); +void git_oidmap_set_key_at(git_oidmap *map, size_t idx, git_oid *key); +void *git_oidmap_value_at(git_oidmap *map, size_t idx); +void git_oidmap_set_value_at(git_oidmap *map, size_t idx, void *value); +void git_oidmap_delete_at(git_oidmap *map, size_t idx); -#define git_oidmap_insert(h, key, val, rval) do { \ - khiter_t __pos = kh_put(oid, h, key, rval); \ - if ((*rval) >= 0) { \ - if ((*rval) == 0) kh_key(h, __pos) = key; \ - kh_val(h, __pos) = val; \ - } } while (0) +int git_oidmap_put(git_oidmap *map, const git_oid *key, int *err); +void git_oidmap_insert(git_oidmap *map, const git_oid *key, void *value, int *rval); +void git_oidmap_delete(git_oidmap *map, const git_oid *key); #define git_oidmap_foreach_value kh_foreach_value #define git_oidmap_begin kh_begin #define git_oidmap_end kh_end -#define git_oidmap_size(h) kh_size(h) - -#define git_oidmap_clear(h) kh_clear(oid, h) - #endif From 0d71690549b918d0aafc5873229661a43eee9eed Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 27 Jan 2017 15:23:15 +0100 Subject: [PATCH 130/366] oidmap: remove GIT__USE_OIDMAP macro --- src/cache.c | 2 -- src/describe.c | 2 -- src/indexer.c | 2 -- src/odb_mempack.c | 2 -- src/oidmap.c | 7 +++++++ src/oidmap.h | 10 ---------- src/pack-objects.c | 2 -- src/pack.c | 1 - src/revwalk.c | 2 -- tests/core/oidmap.c | 2 -- 10 files changed, 7 insertions(+), 25 deletions(-) diff --git a/src/cache.c b/src/cache.c index f76e72d93..c92a3a78a 100644 --- a/src/cache.c +++ b/src/cache.c @@ -15,8 +15,6 @@ #include "object.h" #include "git2/oid.h" -GIT__USE_OIDMAP - bool git_cache__enabled = true; ssize_t git_cache__max_storage = (256 * 1024 * 1024); git_atomic_ssize git_cache__current_storage = {0}; diff --git a/src/describe.c b/src/describe.c index 152385836..4a1e25378 100644 --- a/src/describe.c +++ b/src/describe.c @@ -19,8 +19,6 @@ #include "vector.h" #include "repository.h" -GIT__USE_OIDMAP - /* Ported from https://github.com/git/git/blob/89dde7882f71f846ccd0359756d27bebc31108de/builtin/describe.c */ struct commit_name { diff --git a/src/indexer.c b/src/indexer.c index 3e88bc7ba..869e2299f 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -18,8 +18,6 @@ #include "oidmap.h" #include "zstream.h" -GIT__USE_OIDMAP - extern git_mutex git__mwindow_mutex; #define UINT31_MAX (0x7FFFFFFF) diff --git a/src/odb_mempack.c b/src/odb_mempack.c index 52f8089e1..d6f2fb4af 100644 --- a/src/odb_mempack.c +++ b/src/odb_mempack.c @@ -18,8 +18,6 @@ #include "git2/types.h" #include "git2/pack.h" -GIT__USE_OIDMAP - struct memobject { git_oid oid; size_t len; diff --git a/src/oidmap.c b/src/oidmap.c index ab821df8d..0df9a4f42 100644 --- a/src/oidmap.c +++ b/src/oidmap.c @@ -7,6 +7,13 @@ #include "oidmap.h" +GIT_INLINE(khint_t) git_oidmap_hash(const git_oid *oid) +{ + khint_t h; + memcpy(&h, oid, sizeof(khint_t)); + return h; +} + __KHASH_IMPL(oid, static kh_inline, const git_oid *, void *, 1, git_oidmap_hash, git_oid_equal) git_oidmap *git_oidmap_alloc() diff --git a/src/oidmap.h b/src/oidmap.h index bfad8e2ad..a3f8961dc 100644 --- a/src/oidmap.h +++ b/src/oidmap.h @@ -20,16 +20,6 @@ __KHASH_TYPE(oid, const git_oid *, void *) typedef khash_t(oid) git_oidmap; -GIT_INLINE(khint_t) git_oidmap_hash(const git_oid *oid) -{ - khint_t h; - memcpy(&h, oid, sizeof(khint_t)); - return h; -} - -#define GIT__USE_OIDMAP \ - __KHASH_IMPL(oid, static kh_inline, const git_oid *, void *, 1, git_oidmap_hash, git_oid_equal) - git_oidmap *git_oidmap_alloc(void); #define git_oidmap_free(h) git_oidmap__free(h); (h) = NULL void git_oidmap__free(git_oidmap *map); diff --git a/src/pack-objects.c b/src/pack-objects.c index 1b4ec9d15..58b7b94b3 100644 --- a/src/pack-objects.c +++ b/src/pack-objects.c @@ -41,8 +41,6 @@ struct pack_write_context { git_transfer_progress *stats; }; -GIT__USE_OIDMAP - #ifdef GIT_THREADS #define GIT_PACKBUILDER__MUTEX_OP(pb, mtx, op) do { \ diff --git a/src/pack.c b/src/pack.c index 4e30ca7c3..9be051e64 100644 --- a/src/pack.c +++ b/src/pack.c @@ -17,7 +17,6 @@ #include GIT__USE_OFFMAP -GIT__USE_OIDMAP static int packfile_open(struct git_pack_file *p); static git_off_t nth_packed_object_offset(const struct git_pack_file *p, uint32_t n); diff --git a/src/revwalk.c b/src/revwalk.c index ac5400253..6d08164ba 100644 --- a/src/revwalk.c +++ b/src/revwalk.c @@ -15,8 +15,6 @@ #include "merge.h" #include "vector.h" -GIT__USE_OIDMAP - git_commit_list_node *git_revwalk__commit_lookup( git_revwalk *walk, const git_oid *oid) { diff --git a/tests/core/oidmap.c b/tests/core/oidmap.c index 92b8c1937..617da5483 100644 --- a/tests/core/oidmap.c +++ b/tests/core/oidmap.c @@ -1,8 +1,6 @@ #include "clar_libgit2.h" #include "oidmap.h" -GIT__USE_OIDMAP - typedef struct { git_oid oid; size_t extra; From cf6124d68b8a7a2b98e7191fa4c4a5a149c09420 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Thu, 2 Feb 2017 11:57:31 +0100 Subject: [PATCH 131/366] offmap: convert to use functions instead of macros --- src/offmap.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/offmap.h | 37 +++++++++-------------- 2 files changed, 97 insertions(+), 23 deletions(-) create mode 100644 src/offmap.c diff --git a/src/offmap.c b/src/offmap.c new file mode 100644 index 000000000..3f51f6e0c --- /dev/null +++ b/src/offmap.c @@ -0,0 +1,83 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#include "offmap.h" + +GIT__USE_OFFMAP + +git_offmap *git_offmap_alloc(void) +{ + return kh_init(off); +} + +void git_offmap__free(git_offmap *map) +{ + kh_destroy(off, map); +} + +void git_offmap_clear(git_offmap *map) +{ + kh_clear(off, map); +} + +size_t git_offmap_num_entries(git_offmap *map) +{ + return kh_size(map); +} + +size_t git_offmap_lookup_index(git_offmap *map, const git_off_t key) +{ + return kh_get(off, map, key); +} + +int git_offmap_valid_index(git_offmap *map, size_t idx) +{ + return idx != kh_end(map); +} + +int git_offmap_exists(git_offmap *map, const git_off_t key) +{ + return kh_get(off, map, key) != kh_end(map); +} + +void *git_offmap_value_at(git_offmap *map, size_t idx) +{ + return kh_val(map, idx); +} + +void git_offmap_set_value_at(git_offmap *map, size_t idx, void *value) +{ + kh_val(map, idx) = value; +} + +void git_offmap_delete_at(git_offmap *map, size_t idx) +{ + kh_del(off, map, idx); +} + +int git_offmap_put(git_offmap *map, const git_off_t key, int *err) +{ + return kh_put(off, map, key, err); +} + +void git_offmap_insert(git_offmap *map, const git_off_t key, void *value, int *rval) +{ + khiter_t idx = kh_put(off, map, key, rval); + + if ((*rval) >= 0) { + if ((*rval) == 0) + kh_key(map, idx) = key; + kh_val(map, idx) = value; + } +} + +void git_offmap_delete(git_offmap *map, const git_off_t key) +{ + khiter_t idx = git_offmap_lookup_index(map, key); + if (git_offmap_valid_index(map, idx)) + git_offmap_delete_at(map, idx); +} diff --git a/src/offmap.h b/src/offmap.h index 56003cf62..db79e485e 100644 --- a/src/offmap.h +++ b/src/offmap.h @@ -23,34 +23,25 @@ typedef khash_t(off) git_offmap; #define GIT__USE_OFFMAP \ __KHASH_IMPL(off, static kh_inline, git_off_t, void *, 1, kh_int64_hash_func, kh_int64_hash_equal) -#define git_offmap_alloc() kh_init(off) -#define git_offmap_free(h) kh_destroy(off, h), h = NULL -#define git_offmap_clear(h) kh_clear(off, h) +git_offmap *git_offmap_alloc(void); +#define git_offmap_free(h) git_offmap__free(h); (h) = NULL +void git_offmap__free(git_offmap *map); +void git_offmap_clear(git_offmap *map); -#define git_offmap_num_entries(h) kh_size(h) +size_t git_offmap_num_entries(git_offmap *map); -#define git_offmap_lookup_index(h, k) kh_get(off, h, k) -#define git_offmap_valid_index(h, idx) (idx != kh_end(h)) +size_t git_offmap_lookup_index(git_offmap *map, const git_off_t key); +int git_offmap_valid_index(git_offmap *map, size_t idx); -#define git_offmap_exists(h, k) (kh_get(off, h, k) != kh_end(h)) +int git_offmap_exists(git_offmap *map, const git_off_t key); -#define git_offmap_value_at(h, idx) kh_val(h, idx) -#define git_offmap_set_value_at(h, idx, v) kh_val(h, idx) = v -#define git_offmap_delete_at(h, idx) kh_del(off, h, idx) +void *git_offmap_value_at(git_offmap *map, size_t idx); +void git_offmap_set_value_at(git_offmap *map, size_t idx, void *value); +void git_offmap_delete_at(git_offmap *map, size_t idx); -#define git_offmap_put(h, k, err) kh_put(off, h, k, err) - -#define git_offmap_insert(h, key, val, rval) do { \ - khiter_t __pos = kh_put(off, h, key, rval); \ - if ((*rval) >= 0) { \ - if ((*rval) == 0) kh_key(h, __pos) = key; \ - kh_val(h, __pos) = val; \ - } } while (0) - -#define git_offmap_delete(h, key) do { \ - khiter_t __pos = git_offmap_lookup_index(h, key); \ - if (git_offmap_valid_index(h, __pos)) \ - git_offmap_delete_at(h, __pos); } while (0) +int git_offmap_put(git_offmap *map, const git_off_t key, int *err); +void git_offmap_insert(git_offmap *map, const git_off_t key, void *value, int *rval); +void git_offmap_delete(git_offmap *map, const git_off_t key); #define git_offmap_foreach kh_foreach #define git_offmap_foreach_value kh_foreach_value From 8f5fe903d629309cf711bf3c7a0c8e9b6826b0a0 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Thu, 2 Feb 2017 11:58:48 +0100 Subject: [PATCH 132/366] offmap: remove GIT__USE_OFFMAP macro --- src/offmap.c | 2 +- src/offmap.h | 3 --- src/pack.c | 2 -- 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/offmap.c b/src/offmap.c index 3f51f6e0c..023c9b417 100644 --- a/src/offmap.c +++ b/src/offmap.c @@ -7,7 +7,7 @@ #include "offmap.h" -GIT__USE_OFFMAP +__KHASH_IMPL(off, static kh_inline, git_off_t, void *, 1, kh_int64_hash_func, kh_int64_hash_equal) git_offmap *git_offmap_alloc(void) { diff --git a/src/offmap.h b/src/offmap.h index db79e485e..1f30cda6d 100644 --- a/src/offmap.h +++ b/src/offmap.h @@ -20,9 +20,6 @@ __KHASH_TYPE(off, git_off_t, void *) typedef khash_t(off) git_offmap; -#define GIT__USE_OFFMAP \ - __KHASH_IMPL(off, static kh_inline, git_off_t, void *, 1, kh_int64_hash_func, kh_int64_hash_equal) - git_offmap *git_offmap_alloc(void); #define git_offmap_free(h) git_offmap__free(h); (h) = NULL void git_offmap__free(git_offmap *map); diff --git a/src/pack.c b/src/pack.c index 9be051e64..d59fae412 100644 --- a/src/pack.c +++ b/src/pack.c @@ -16,8 +16,6 @@ #include -GIT__USE_OFFMAP - static int packfile_open(struct git_pack_file *p); static git_off_t nth_packed_object_offset(const struct git_pack_file *p, uint32_t n); static int packfile_unpack_compressed( From cee9ca6609466c63886218290e9ecad5f703094b Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Thu, 2 Feb 2017 12:20:17 +0100 Subject: [PATCH 133/366] idxmap: convert to use functions instead of macros --- src/idxmap.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/idxmap.h | 57 ++++++++---------------- 2 files changed, 139 insertions(+), 39 deletions(-) create mode 100644 src/idxmap.c diff --git a/src/idxmap.c b/src/idxmap.c new file mode 100644 index 000000000..490824017 --- /dev/null +++ b/src/idxmap.c @@ -0,0 +1,121 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#include "idxmap.h" + +GIT__USE_IDXMAP +GIT__USE_IDXMAP_ICASE + +int git_idxmap_alloc(git_idxmap **map) +{ + if ((*map = kh_init(idx)) == NULL) { + giterr_set_oom(); + return -1; + } + + return 0; +} + +int git_idxmap_icase_alloc(git_idxmap_icase **map) +{ + if ((*map = kh_init(idxicase)) == NULL) { + giterr_set_oom(); + return -1; + } + + return 0; +} + +void git_idxmap_insert(git_idxmap *map, const git_index_entry *key, void *value, int *rval) +{ + khiter_t idx = kh_put(idx, map, key, rval); + + if ((*rval) >= 0) { + if ((*rval) == 0) + kh_key(map, idx) = key; + kh_val(map, idx) = value; + } +} + +void git_idxmap_icase_insert(git_idxmap_icase *map, const git_index_entry *key, void *value, int *rval) +{ + khiter_t idx = kh_put(idxicase, map, key, rval); + + if ((*rval) >= 0) { + if ((*rval) == 0) + kh_key(map, idx) = key; + kh_val(map, idx) = value; + } +} + +size_t git_idxmap_lookup_index(git_idxmap *map, const git_index_entry *key) +{ + return kh_get(idx, map, key); +} + +size_t git_idxmap_icase_lookup_index(git_idxmap_icase *map, const git_index_entry *key) +{ + return kh_get(idxicase, map, key); +} + +void *git_idxmap_value_at(git_idxmap *map, size_t idx) +{ + return kh_val(map, idx); +} + +int git_idxmap_valid_index(git_idxmap *map, size_t idx) +{ + return idx != kh_end(map); +} + +int git_idxmap_has_data(git_idxmap *map, size_t idx) +{ + return kh_exist(map, idx); +} + +void git_idxmap_resize(git_idxmap *map, size_t size) +{ + kh_resize(idx, map, size); +} + +void git_idxmap_icase_resize(git_idxmap_icase *map, size_t size) +{ + kh_resize(idxicase, map, size); +} + +void git_idxmap__free(git_idxmap *map) +{ + kh_destroy(idx, map); +} + +void git_idxmap_clear(git_idxmap *map) +{ + kh_clear(idx, map); +} + +void git_idxmap_delete_at(git_idxmap *map, size_t idx) +{ + kh_del(idx, map, idx); +} + +void git_idxmap_icase_delete_at(git_idxmap_icase *map, size_t idx) +{ + kh_del(idxicase, map, idx); +} + +void git_idxmap_delete(git_idxmap *map, const git_index_entry *key) +{ + khiter_t idx = git_idxmap_lookup_index(map, key); + if (git_idxmap_valid_index(map, idx)) + git_idxmap_delete_at(map, idx); +} +void git_idxmap_icase_delete(git_idxmap_icase *map, const git_index_entry *key) +{ + khiter_t idx = git_idxmap_icase_lookup_index(map, key); + if (git_idxmap_valid_index((git_idxmap *)map, idx)) + git_idxmap_icase_delete_at(map, idx); +} diff --git a/src/idxmap.h b/src/idxmap.h index 21de5af78..aaca50b48 100644 --- a/src/idxmap.h +++ b/src/idxmap.h @@ -44,49 +44,28 @@ static kh_inline khint_t idxentry_hash(const git_index_entry *e) #define GIT__USE_IDXMAP_ICASE \ __KHASH_IMPL(idxicase, static kh_inline, const git_index_entry *, git_index_entry *, 1, idxentry_hash, idxentry_icase_equal) -#define git_idxmap_alloc(hp) \ - ((*(hp) = kh_init(idx)) == NULL) ? giterr_set_oom(), -1 : 0 +int git_idxmap_alloc(git_idxmap **map); +int git_idxmap_icase_alloc(git_idxmap_icase **map); +void git_idxmap_insert(git_idxmap *map, const git_index_entry *key, void *value, int *rval); +void git_idxmap_icase_insert(git_idxmap_icase *map, const git_index_entry *key, void *value, int *rval); -#define git_idxmap_icase_alloc(hp) \ - ((*(hp) = kh_init(idxicase)) == NULL) ? giterr_set_oom(), -1 : 0 +size_t git_idxmap_lookup_index(git_idxmap *map, const git_index_entry *key); +size_t git_idxmap_icase_lookup_index(git_idxmap_icase *map, const git_index_entry *key); +void *git_idxmap_value_at(git_idxmap *map, size_t idx); +int git_idxmap_valid_index(git_idxmap *map, size_t idx); +int git_idxmap_has_data(git_idxmap *map, size_t idx); -#define git_idxmap_insert(h, key, val, rval) do { \ - khiter_t __pos = kh_put(idx, h, key, rval); \ - if ((*rval) >= 0) { \ - if ((*rval) == 0) kh_key(h, __pos) = key; \ - kh_val(h, __pos) = val; \ - } } while (0) +void git_idxmap_resize(git_idxmap *map, size_t size); +void git_idxmap_icase_resize(git_idxmap_icase *map, size_t size); +#define git_idxmap_free(h) git_idxmap__free(h); (h) = NULL +void git_idxmap__free(git_idxmap *map); +void git_idxmap_clear(git_idxmap *map); -#define git_idxmap_icase_insert(h, key, val, rval) do { \ - khiter_t __pos = kh_put(idxicase, h, key, rval); \ - if ((*rval) >= 0) { \ - if ((*rval) == 0) kh_key(h, __pos) = key; \ - kh_val(h, __pos) = val; \ - } } while (0) +void git_idxmap_delete_at(git_idxmap *map, size_t idx); +void git_idxmap_icase_delete_at(git_idxmap_icase *map, size_t idx); -#define git_idxmap_lookup_index(h, k) kh_get(idx, h, k) -#define git_idxmap_icase_lookup_index(h, k) kh_get(idxicase, h, k) -#define git_idxmap_value_at(h, idx) kh_val(h, idx) -#define git_idxmap_valid_index(h, idx) (idx != kh_end(h)) -#define git_idxmap_has_data(h, idx) kh_exist(h, idx) - -#define git_idxmap_resize(h,s) kh_resize(idx, h, s) -#define git_idxmap_icase_resize(h,s) kh_resize(idxicase, h, s) -#define git_idxmap_free(h) kh_destroy(idx, h), h = NULL -#define git_idxmap_clear(h) kh_clear(idx, h) - -#define git_idxmap_delete_at(h, id) kh_del(idx, h, id) -#define git_idxmap_icase_delete_at(h, id) kh_del(idxicase, h, id) - -#define git_idxmap_delete(h, key) do { \ - khiter_t __pos = git_idxmap_lookup_index(h, key); \ - if (git_idxmap_valid_index(h, __pos)) \ - git_idxmap_delete_at(h, __pos); } while (0) - -#define git_idxmap_icase_delete(h, key) do { \ - khiter_t __pos = git_idxmap_icase_lookup_index(h, key); \ - if (git_idxmap_valid_index(h, __pos)) \ - git_idxmap_icase_delete_at(h, __pos); } while (0) +void git_idxmap_delete(git_idxmap *map, const git_index_entry *key); +void git_idxmap_icase_delete(git_idxmap_icase *map, const git_index_entry *key); #define git_idxmap_begin kh_begin #define git_idxmap_end kh_end From 8f1ff26bd3c46d7f4f20b6776fd2edac647f3335 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Thu, 2 Feb 2017 13:09:32 +0100 Subject: [PATCH 134/366] idxmap: remove GIT__USE_IDXMAP --- src/idxmap.c | 16 ++++++++++++++-- src/idxmap.h | 18 ------------------ src/index.c | 3 --- 3 files changed, 14 insertions(+), 23 deletions(-) diff --git a/src/idxmap.c b/src/idxmap.c index 490824017..10f55ad39 100644 --- a/src/idxmap.c +++ b/src/idxmap.c @@ -7,8 +7,20 @@ #include "idxmap.h" -GIT__USE_IDXMAP -GIT__USE_IDXMAP_ICASE +/* This is __ac_X31_hash_string but with tolower and it takes the entry's stage into account */ +static kh_inline khint_t idxentry_hash(const git_index_entry *e) +{ + const char *s = e->path; + khint_t h = (khint_t)git__tolower(*s); + if (h) for (++s ; *s; ++s) h = (h << 5) - h + (khint_t)git__tolower(*s); + return h + GIT_IDXENTRY_STAGE(e); +} + +#define idxentry_equal(a, b) (GIT_IDXENTRY_STAGE(a) == GIT_IDXENTRY_STAGE(b) && strcmp(a->path, b->path) == 0) +#define idxentry_icase_equal(a, b) (GIT_IDXENTRY_STAGE(a) == GIT_IDXENTRY_STAGE(b) && strcasecmp(a->path, b->path) == 0) + +__KHASH_IMPL(idx, static kh_inline, const git_index_entry *, git_index_entry *, 1, idxentry_hash, idxentry_equal) +__KHASH_IMPL(idxicase, static kh_inline, const git_index_entry *, git_index_entry *, 1, idxentry_hash, idxentry_icase_equal) int git_idxmap_alloc(git_idxmap **map) { diff --git a/src/idxmap.h b/src/idxmap.h index aaca50b48..e4e9ec4cd 100644 --- a/src/idxmap.h +++ b/src/idxmap.h @@ -26,24 +26,6 @@ typedef khash_t(idxicase) git_idxmap_icase; typedef khiter_t git_idxmap_iter; -/* This is __ac_X31_hash_string but with tolower and it takes the entry's stage into account */ -static kh_inline khint_t idxentry_hash(const git_index_entry *e) -{ - const char *s = e->path; - khint_t h = (khint_t)git__tolower(*s); - if (h) for (++s ; *s; ++s) h = (h << 5) - h + (khint_t)git__tolower(*s); - return h + GIT_IDXENTRY_STAGE(e); -} - -#define idxentry_equal(a, b) (GIT_IDXENTRY_STAGE(a) == GIT_IDXENTRY_STAGE(b) && strcmp(a->path, b->path) == 0) -#define idxentry_icase_equal(a, b) (GIT_IDXENTRY_STAGE(a) == GIT_IDXENTRY_STAGE(b) && strcasecmp(a->path, b->path) == 0) - -#define GIT__USE_IDXMAP \ - __KHASH_IMPL(idx, static kh_inline, const git_index_entry *, git_index_entry *, 1, idxentry_hash, idxentry_equal) - -#define GIT__USE_IDXMAP_ICASE \ - __KHASH_IMPL(idxicase, static kh_inline, const git_index_entry *, git_index_entry *, 1, idxentry_hash, idxentry_icase_equal) - int git_idxmap_alloc(git_idxmap **map); int git_idxmap_icase_alloc(git_idxmap_icase **map); void git_idxmap_insert(git_idxmap *map, const git_index_entry *key, void *value, int *rval); diff --git a/src/index.c b/src/index.c index 7b510e04e..932a5306a 100644 --- a/src/index.c +++ b/src/index.c @@ -27,9 +27,6 @@ #include "git2/config.h" #include "git2/sys/index.h" -GIT__USE_IDXMAP -GIT__USE_IDXMAP_ICASE - #define INSERT_IN_MAP_EX(idx, map, e, err) do { \ if ((idx)->ignore_case) \ git_idxmap_icase_insert((khash_t(idxicase) *) (map), (e), (e), (err)); \ From cc172642702e59637ee237317c0d6fab903d176f Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 17 Feb 2017 12:10:19 +0000 Subject: [PATCH 135/366] p_snprintf: no need for arguments to a format `snprintf` requires a _format_ but does not require _arguments_ to the format. eg: `snprintf(buf, 42, "hi")` is perfectly legal. Expand the macro to match. Without this, `p_sprintf(buf, 42, "hi")` errors with: ``` error: expected expression p_snprintf(msg, 42, "hi"); ^ src/unix/posix.h:53:34: note: expanded from macro 'p_snprintf' ^ /usr/include/secure/_stdio.h:57:73: note: expanded from macro 'snprintf' __builtin___snprintf_chk (str, len, 0, __darwin_obsz(str), __VA_ARGS__) ``` --- src/unix/posix.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/unix/posix.h b/src/unix/posix.h index ad13291e8..b4786403f 100644 --- a/src/unix/posix.h +++ b/src/unix/posix.h @@ -50,7 +50,7 @@ extern char *p_realpath(const char *, char *); #define p_strcasecmp(s1, s2) strcasecmp(s1, s2) #define p_strncasecmp(s1, s2, c) strncasecmp(s1, s2, c) #define p_vsnprintf(b, c, f, a) vsnprintf(b, c, f, a) -#define p_snprintf(b, c, f, ...) snprintf(b, c, f, __VA_ARGS__) +#define p_snprintf(b, c, ...) snprintf(b, c, __VA_ARGS__) #define p_mkstemp(p) mkstemp(p) #define p_chdir(p) chdir(p) #define p_chmod(p,m) chmod(p, m) From a1dcc83030f9073fe29054ecaf7647dca1fec2ec Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 17 Feb 2017 12:13:35 +0000 Subject: [PATCH 136/366] tests: provide better pass/failure error messages Provide more detailed messages when conditions pass or fail unexpectedly. In particular, this provides the error messages when a test fails with a different error code than was expected. --- tests/attr/ignore.c | 4 ++-- tests/clar_libgit2.c | 14 +++++++++++--- tests/clar_libgit2.h | 22 +++++++++++++--------- tests/repo/env.c | 12 ++++++------ tests/status/ignore.c | 4 ++-- tests/submodule/submodule_helpers.c | 2 +- 6 files changed, 35 insertions(+), 23 deletions(-) diff --git a/tests/attr/ignore.c b/tests/attr/ignore.c index f1fe1c71f..a8845e463 100644 --- a/tests/attr/ignore.c +++ b/tests/attr/ignore.c @@ -21,8 +21,8 @@ static void assert_is_ignored_( { int is_ignored = 0; - cl_git_pass_( - git_ignore_path_is_ignored(&is_ignored, g_repo, filepath), file, line); + cl_git_exec( + git_ignore_path_is_ignored(&is_ignored, g_repo, filepath), 0, file, line); clar__assert_equal( file, line, "expected != is_ignored", 1, "%d", diff --git a/tests/clar_libgit2.c b/tests/clar_libgit2.c index 314d3441e..bd10c009d 100644 --- a/tests/clar_libgit2.c +++ b/tests/clar_libgit2.c @@ -4,12 +4,20 @@ #include "git2/sys/repository.h" void cl_git_report_failure( - int error, const char *file, int line, const char *fncall) + int error, int expected, const char *file, int line, const char *fncall) { char msg[4096]; const git_error *last = giterr_last(); - p_snprintf(msg, 4096, "error %d - %s", - error, last ? last->message : ""); + + if (expected) + p_snprintf(msg, 4096, "error %d (expected %d) - %s", + error, expected, last ? last->message : ""); + else if (error || last) + p_snprintf(msg, 4096, "error %d - %s", + error, last ? last->message : ""); + else + p_snprintf(msg, 4096, "no error, expected non-zero return"); + clar__assert(0, file, line, fncall, msg, 1); } diff --git a/tests/clar_libgit2.h b/tests/clar_libgit2.h index fc08bbf1f..1d77bc6d6 100644 --- a/tests/clar_libgit2.h +++ b/tests/clar_libgit2.h @@ -12,13 +12,15 @@ * * Use this wrapper around all `git_` library calls that return error codes! */ -#define cl_git_pass(expr) cl_git_pass_((expr), __FILE__, __LINE__) +#define cl_git_pass(expr) cl_git_exec((expr), 0, __FILE__, __LINE__) -#define cl_git_pass_(expr, file, line) do { \ +#define cl_git_fail_with(error, expr) cl_git_exec((expr), error, __FILE__, __LINE__) + +#define cl_git_exec(expr, expected, file, line) do { \ int _lg2_error; \ giterr_clear(); \ - if ((_lg2_error = (expr)) != 0) \ - cl_git_report_failure(_lg2_error, file, line, "Function call failed: " #expr); \ + if ((_lg2_error = (expr)) != expected) \ + cl_git_report_failure(_lg2_error, expected, file, line, "Function call failed: " #expr); \ } while (0) /** @@ -26,9 +28,11 @@ * just for consistency. Use with `git_` library * calls that are supposed to fail! */ -#define cl_git_fail(expr) cl_must_fail(expr) - -#define cl_git_fail_with(expr, error) cl_assert_equal_i(error,expr) +#define cl_git_fail(expr) do { \ + giterr_clear(); \ + if ((expr) == 0) \ + cl_git_report_failure(0, 0, __FILE__, __LINE__, "Function call succeeded: " #expr); \ + } while (0) /** * Like cl_git_pass, only for Win32 error code conventions @@ -37,7 +41,7 @@ int _win32_res; \ if ((_win32_res = (expr)) == 0) { \ giterr_set(GITERR_OS, "Returned: %d, system error code: %d", _win32_res, GetLastError()); \ - cl_git_report_failure(_win32_res, __FILE__, __LINE__, "System call failed: " #expr); \ + cl_git_report_failure(_win32_res, 0, __FILE__, __LINE__, "System call failed: " #expr); \ } \ } while(0) @@ -86,7 +90,7 @@ GIT_INLINE(void) cl_git_thread_check(void *data) clar__assert(0, threaderr->file, threaderr->line, threaderr->expr, threaderr->error_msg, 1); } -void cl_git_report_failure(int, const char *, int, const char *); +void cl_git_report_failure(int, int, const char *, int, const char *); #define cl_assert_at_line(expr,file,line) \ clar__assert((expr) != 0, file, line, "Expression is not true: " #expr, NULL, 1) diff --git a/tests/repo/env.c b/tests/repo/env.c index 5a89c0d49..235f787ab 100644 --- a/tests/repo/env.c +++ b/tests/repo/env.c @@ -56,8 +56,8 @@ static int GIT_FORMAT_PRINTF(2, 3) cl_setenv_printf(const char *name, const char static void env_pass_(const char *path, const char *file, int line) { git_repository *repo; - cl_git_pass_(git_repository_open_ext(NULL, path, GIT_REPOSITORY_OPEN_FROM_ENV, NULL), file, line); - cl_git_pass_(git_repository_open_ext(&repo, path, GIT_REPOSITORY_OPEN_FROM_ENV, NULL), file, line); + cl_git_exec(git_repository_open_ext(NULL, path, GIT_REPOSITORY_OPEN_FROM_ENV, NULL), 0, file, line); + cl_git_exec(git_repository_open_ext(&repo, path, GIT_REPOSITORY_OPEN_FROM_ENV, NULL), 0, file, line); cl_assert_at_line(git__suffixcmp(git_repository_path(repo), "attr/.git/") == 0, file, line); cl_assert_at_line(git__suffixcmp(git_repository_workdir(repo), "attr/") == 0, file, line); cl_assert_at_line(!git_repository_is_bare(repo), file, line); @@ -98,24 +98,24 @@ static void env_check_objects_(bool a, bool t, bool p, const char *file, int lin cl_git_pass(git_oid_fromstr(&oid_a, "45141a79a77842c59a63229403220a4e4be74e3d")); cl_git_pass(git_oid_fromstr(&oid_t, "1385f264afb75a56a5bec74243be9b367ba4ca08")); cl_git_pass(git_oid_fromstr(&oid_p, "0df1a5865c8abfc09f1f2182e6a31be550e99f07")); - cl_git_pass_(git_repository_open_ext(&repo, "attr", GIT_REPOSITORY_OPEN_FROM_ENV, NULL), file, line); + cl_git_exec(git_repository_open_ext(&repo, "attr", GIT_REPOSITORY_OPEN_FROM_ENV, NULL), 0, file, line); if (a) { - cl_git_pass_(git_object_lookup(&object, repo, &oid_a, GIT_OBJ_BLOB), file, line); + cl_git_exec(git_object_lookup(&object, repo, &oid_a, GIT_OBJ_BLOB), 0, file, line); git_object_free(object); } else { cl_git_fail_at_line(git_object_lookup(&object, repo, &oid_a, GIT_OBJ_BLOB), file, line); } if (t) { - cl_git_pass_(git_object_lookup(&object, repo, &oid_t, GIT_OBJ_BLOB), file, line); + cl_git_exec(git_object_lookup(&object, repo, &oid_t, GIT_OBJ_BLOB), 0, file, line); git_object_free(object); } else { cl_git_fail_at_line(git_object_lookup(&object, repo, &oid_t, GIT_OBJ_BLOB), file, line); } if (p) { - cl_git_pass_(git_object_lookup(&object, repo, &oid_p, GIT_OBJ_COMMIT), file, line); + cl_git_exec(git_object_lookup(&object, repo, &oid_p, GIT_OBJ_COMMIT), 0, file, line); git_object_free(object); } else { cl_git_fail_at_line(git_object_lookup(&object, repo, &oid_p, GIT_OBJ_COMMIT), file, line); diff --git a/tests/status/ignore.c b/tests/status/ignore.c index c4878b2dd..a9b96114b 100644 --- a/tests/status/ignore.c +++ b/tests/status/ignore.c @@ -20,8 +20,8 @@ static void assert_ignored_( bool expected, const char *filepath, const char *file, int line) { int is_ignored = 0; - cl_git_pass_( - git_status_should_ignore(&is_ignored, g_repo, filepath), file, line); + cl_git_exec( + git_status_should_ignore(&is_ignored, g_repo, filepath), 0, file, line); clar__assert( (expected != 0) == (is_ignored != 0), file, line, "expected != is_ignored", filepath, 1); diff --git a/tests/submodule/submodule_helpers.c b/tests/submodule/submodule_helpers.c index 6c2b9cf78..cd541ea86 100644 --- a/tests/submodule/submodule_helpers.c +++ b/tests/submodule/submodule_helpers.c @@ -204,7 +204,7 @@ void assert__submodule_exists( git_submodule *sm; int error = git_submodule_lookup(&sm, repo, name); if (error) - cl_git_report_failure(error, file, line, msg); + cl_git_report_failure(error, 0, file, line, msg); cl_assert_at_line(sm != NULL, file, line); git_submodule_free(sm); } From c52480fde52c6d65b8ded9ba65bce0b15ff312df Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 17 Feb 2017 13:01:49 +0000 Subject: [PATCH 137/366] `cl_git_exec` -> `cl_git_expect` --- tests/attr/ignore.c | 2 +- tests/clar_libgit2.h | 6 +++--- tests/repo/env.c | 12 ++++++------ tests/status/ignore.c | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/attr/ignore.c b/tests/attr/ignore.c index a8845e463..3a193890a 100644 --- a/tests/attr/ignore.c +++ b/tests/attr/ignore.c @@ -21,7 +21,7 @@ static void assert_is_ignored_( { int is_ignored = 0; - cl_git_exec( + cl_git_expect( git_ignore_path_is_ignored(&is_ignored, g_repo, filepath), 0, file, line); clar__assert_equal( diff --git a/tests/clar_libgit2.h b/tests/clar_libgit2.h index 1d77bc6d6..c72d37db3 100644 --- a/tests/clar_libgit2.h +++ b/tests/clar_libgit2.h @@ -12,11 +12,11 @@ * * Use this wrapper around all `git_` library calls that return error codes! */ -#define cl_git_pass(expr) cl_git_exec((expr), 0, __FILE__, __LINE__) +#define cl_git_pass(expr) cl_git_expect((expr), 0, __FILE__, __LINE__) -#define cl_git_fail_with(error, expr) cl_git_exec((expr), error, __FILE__, __LINE__) +#define cl_git_fail_with(error, expr) cl_git_expect((expr), error, __FILE__, __LINE__) -#define cl_git_exec(expr, expected, file, line) do { \ +#define cl_git_expect(expr, expected, file, line) do { \ int _lg2_error; \ giterr_clear(); \ if ((_lg2_error = (expr)) != expected) \ diff --git a/tests/repo/env.c b/tests/repo/env.c index 235f787ab..6404f88e9 100644 --- a/tests/repo/env.c +++ b/tests/repo/env.c @@ -56,8 +56,8 @@ static int GIT_FORMAT_PRINTF(2, 3) cl_setenv_printf(const char *name, const char static void env_pass_(const char *path, const char *file, int line) { git_repository *repo; - cl_git_exec(git_repository_open_ext(NULL, path, GIT_REPOSITORY_OPEN_FROM_ENV, NULL), 0, file, line); - cl_git_exec(git_repository_open_ext(&repo, path, GIT_REPOSITORY_OPEN_FROM_ENV, NULL), 0, file, line); + cl_git_expect(git_repository_open_ext(NULL, path, GIT_REPOSITORY_OPEN_FROM_ENV, NULL), 0, file, line); + cl_git_expect(git_repository_open_ext(&repo, path, GIT_REPOSITORY_OPEN_FROM_ENV, NULL), 0, file, line); cl_assert_at_line(git__suffixcmp(git_repository_path(repo), "attr/.git/") == 0, file, line); cl_assert_at_line(git__suffixcmp(git_repository_workdir(repo), "attr/") == 0, file, line); cl_assert_at_line(!git_repository_is_bare(repo), file, line); @@ -98,24 +98,24 @@ static void env_check_objects_(bool a, bool t, bool p, const char *file, int lin cl_git_pass(git_oid_fromstr(&oid_a, "45141a79a77842c59a63229403220a4e4be74e3d")); cl_git_pass(git_oid_fromstr(&oid_t, "1385f264afb75a56a5bec74243be9b367ba4ca08")); cl_git_pass(git_oid_fromstr(&oid_p, "0df1a5865c8abfc09f1f2182e6a31be550e99f07")); - cl_git_exec(git_repository_open_ext(&repo, "attr", GIT_REPOSITORY_OPEN_FROM_ENV, NULL), 0, file, line); + cl_git_expect(git_repository_open_ext(&repo, "attr", GIT_REPOSITORY_OPEN_FROM_ENV, NULL), 0, file, line); if (a) { - cl_git_exec(git_object_lookup(&object, repo, &oid_a, GIT_OBJ_BLOB), 0, file, line); + cl_git_expect(git_object_lookup(&object, repo, &oid_a, GIT_OBJ_BLOB), 0, file, line); git_object_free(object); } else { cl_git_fail_at_line(git_object_lookup(&object, repo, &oid_a, GIT_OBJ_BLOB), file, line); } if (t) { - cl_git_exec(git_object_lookup(&object, repo, &oid_t, GIT_OBJ_BLOB), 0, file, line); + cl_git_expect(git_object_lookup(&object, repo, &oid_t, GIT_OBJ_BLOB), 0, file, line); git_object_free(object); } else { cl_git_fail_at_line(git_object_lookup(&object, repo, &oid_t, GIT_OBJ_BLOB), file, line); } if (p) { - cl_git_exec(git_object_lookup(&object, repo, &oid_p, GIT_OBJ_COMMIT), 0, file, line); + cl_git_expect(git_object_lookup(&object, repo, &oid_p, GIT_OBJ_COMMIT), 0, file, line); git_object_free(object); } else { cl_git_fail_at_line(git_object_lookup(&object, repo, &oid_p, GIT_OBJ_COMMIT), file, line); diff --git a/tests/status/ignore.c b/tests/status/ignore.c index a9b96114b..251de39dd 100644 --- a/tests/status/ignore.c +++ b/tests/status/ignore.c @@ -20,7 +20,7 @@ static void assert_ignored_( bool expected, const char *filepath, const char *file, int line) { int is_ignored = 0; - cl_git_exec( + cl_git_expect( git_status_should_ignore(&is_ignored, g_repo, filepath), 0, file, line); clar__assert( (expected != 0) == (is_ignored != 0), From b8ab782a6dc206101d78852036a8e86d5b812278 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Tue, 21 Feb 2017 11:43:32 +0100 Subject: [PATCH 138/366] attrcache: do not lock/unlock the mutex directly Improve encapsulation by not referencing the attrcache mutex directly but instead using the `attr_cache_lock` and `attr_cache_unlock` functions. --- src/attrcache.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/attrcache.c b/src/attrcache.c index 6cac14bc3..d460db80c 100644 --- a/src/attrcache.c +++ b/src/attrcache.c @@ -309,7 +309,7 @@ static void attr_cache__free(git_attr_cache *cache) if (!cache) return; - unlock = (git_mutex_lock(&cache->lock) == 0); + unlock = (attr_cache_lock(cache) == 0); if (cache->files != NULL) { git_attr_file_entry *entry; @@ -345,7 +345,7 @@ static void attr_cache__free(git_attr_cache *cache) cache->cfg_excl_file = NULL; if (unlock) - git_mutex_unlock(&cache->lock); + attr_cache_unlock(cache); git_mutex_free(&cache->lock); git__free(cache); @@ -429,7 +429,7 @@ int git_attr_cache__insert_macro(git_repository *repo, git_attr_rule *macro) if (macro->assigns.length == 0) return 0; - if (git_mutex_lock(&cache->lock) < 0) { + if (attr_cache_lock(cache) < 0) { giterr_set(GITERR_OS, "unable to get attr cache lock"); error = -1; } else { From c11510103d9510f1a4b6e3da90464bcef52250c9 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Tue, 21 Feb 2017 11:52:15 +0100 Subject: [PATCH 139/366] attrcache: replace existing file entry with `git__swap` When doing an upsert of a file, we used to use `git__compare_and_swap`, comparing the entry's file which is to be replaced with itself. This can be more easily formulated by using `git__swap`, which unconditionally replaces the value. --- src/attrcache.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/attrcache.c b/src/attrcache.c index d460db80c..1812376ea 100644 --- a/src/attrcache.c +++ b/src/attrcache.c @@ -103,8 +103,11 @@ static int attr_cache_upsert(git_attr_cache *cache, git_attr_file *file) GIT_REFCOUNT_OWN(file, entry); GIT_REFCOUNT_INC(file); - old = git__compare_and_swap( - &entry->file[file->source], entry->file[file->source], file); + /* + * Replace the existing value if another thread has + * created it in the meantime. + */ + old = git__swap(entry->file[file->source], file); if (old) { GIT_REFCOUNT_OWN(old, NULL); From ce6f61daf0e1985d615e640102b5496ff92e401c Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Tue, 21 Feb 2017 15:14:04 +0100 Subject: [PATCH 140/366] attrcache: remove useless `do_init` indirection Remove useless indirection from `git_attr_cache__init` to `git_attr_cache__do_init`. The difference is that the `git_attr_cache__init` macro first checks if the cache is already initialized and, if so, not call `git_attr_cache__do_init`. But actually, `git_attr_cache__do_init` already does the same thing and returns immediately if the cache is already initialized. Remove the indirection. --- src/attrcache.c | 2 +- src/attrcache.h | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/attrcache.c b/src/attrcache.c index 1812376ea..4df14ee2c 100644 --- a/src/attrcache.c +++ b/src/attrcache.c @@ -354,7 +354,7 @@ static void attr_cache__free(git_attr_cache *cache) git__free(cache); } -int git_attr_cache__do_init(git_repository *repo) +int git_attr_cache__init(git_repository *repo) { int ret = 0; git_attr_cache *cache = git_repository_attr_cache(repo); diff --git a/src/attrcache.h b/src/attrcache.h index 44e1ffdce..b91edd3e8 100644 --- a/src/attrcache.h +++ b/src/attrcache.h @@ -22,10 +22,7 @@ typedef struct { git_pool pool; } git_attr_cache; -extern int git_attr_cache__do_init(git_repository *repo); - -#define git_attr_cache__init(REPO) \ - (git_repository_attr_cache(REPO) ? 0 : git_attr_cache__do_init(REPO)) +extern int git_attr_cache__init(git_repository *repo); /* get file - loading and reload as needed */ extern int git_attr_cache__get( From aa5ea47f7382c85d22282a093674f37fe942f116 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Wed, 22 Feb 2017 10:34:19 +0000 Subject: [PATCH 141/366] Provide error on gcc < 4.1 when THREADSAFE Provide a descriptive error message when compiling THREADSAFE on gcc versions < 4.1. We require the atomic primitives (eg `__sync_synchronize`) that were introduced in that version. (Note, clang setes `__GNUC__` but appears to set its version > 4.1.) --- src/thread-utils.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/thread-utils.h b/src/thread-utils.h index f0161989f..2df2aeb99 100644 --- a/src/thread-utils.h +++ b/src/thread-utils.h @@ -7,6 +7,12 @@ #ifndef INCLUDE_thread_utils_h__ #define INCLUDE_thread_utils_h__ +#if defined(__GNUC__) && defined(GIT_THREADS) +# if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 1)) +# error Atomic primitives do not exist on this version of gcc; configure libgit2 with -DTHREADSAFE=OFF +# endif +#endif + /* Common operations even if threading has been disabled */ typedef struct { #if defined(GIT_WIN32) From 685f22519c617e087a74b0754a10ceebc1ec9d77 Mon Sep 17 00:00:00 2001 From: Jason Haslam Date: Wed, 22 Feb 2017 09:29:00 -0700 Subject: [PATCH 142/366] pack: fix looping over cache entries Fixes a regression from #4092. This is a crash on 32-bit and I assume that it doesn't do the right thing on 64-bit either. MSVC emits a warning for this, but of course, it's easy to get lost among all of the similar 'possible loss of data' warnings. --- src/pack.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pack.c b/src/pack.c index d59fae412..60b757e90 100644 --- a/src/pack.c +++ b/src/pack.c @@ -128,13 +128,13 @@ static git_pack_cache_entry *cache_get(git_pack_cache *cache, git_off_t offset) /* Run with the cache lock held */ static void free_lowest_entry(git_pack_cache *cache) { + git_off_t offset; git_pack_cache_entry *entry; - khiter_t k; - git_offmap_foreach(cache->entries, k, entry, { + git_offmap_foreach(cache->entries, offset, entry, { if (entry && entry->refcount.val == 0) { cache->memory_used -= entry->raw.len; - git_offmap_delete_at(cache->entries, k); + git_offmap_delete(cache->entries, offset); free_cache_object(entry); } }); From c3abb1d261ca182f0ead70d64778fa1e13c0794d Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 24 Feb 2017 17:38:42 +0000 Subject: [PATCH 143/366] appveyor: always build the 'appveyor' branch The 'appveyor' branch is useful for testing AppVeyor builds. --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index 9e94c0726..fb3fff7dd 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,6 +2,7 @@ version: '{build}' branches: only: - master + - appveyor - /^maint.*/ environment: GITTEST_INVASIVE_FS_STRUCTURE: 1 From 408a7b7737fd560f5a49bf977287b195ead5c885 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 24 Feb 2017 17:37:00 +0000 Subject: [PATCH 144/366] appveyor: don't rewrite system mingw Download mingw-w64 into our build directory and execute it there, don't try to overwrite the system's mingw. --- script/appveyor-mingw.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/script/appveyor-mingw.sh b/script/appveyor-mingw.sh index 198801875..d171a72d5 100755 --- a/script/appveyor-mingw.sh +++ b/script/appveyor-mingw.sh @@ -7,15 +7,17 @@ if [ "$ARCH" = "i686" ]; then curl -LsSO http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/4.9.2/threads-win32/sjlj/$f fi 7z x $f > /dev/null - mv mingw32 /MinGW + export PATH=`pwd`/mingw32/bin:$PATH else f=x86_64-4.9.2-release-win32-seh-rt_v3-rev1.7z if ! [ -e $f ]; then curl -LsSO http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/4.9.2/threads-win32/seh/$f fi 7z x $f > /dev/null - mv mingw64 /MinGW + export PATH=`pwd`/mingw64/bin:$PATH fi cd build +gcc --version +cmake --version cmake -D ENABLE_TRACE=ON -D BUILD_CLAR=ON .. -G"$GENERATOR" cmake --build . --config RelWithDebInfo From d2b3a21f2b8297881350b5c6b154004da9013711 Mon Sep 17 00:00:00 2001 From: Richard Ipsum Date: Sun, 22 Jan 2017 00:21:30 +0000 Subject: [PATCH 145/366] tests: Add create__symbolic_with_arbitrary_content This test ensures that it's possible to create a symbolic ref that has arbitrary data as its target. It also ensures it's possible to obtain the target of that symbolic reference from the git_reference object. --- tests/refs/create.c | 49 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/tests/refs/create.c b/tests/refs/create.c index 6d5a5f1f6..4196c7487 100644 --- a/tests/refs/create.c +++ b/tests/refs/create.c @@ -20,6 +20,7 @@ void test_refs_create__cleanup(void) cl_git_sandbox_cleanup(); cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_STRICT_OBJECT_CREATION, 1)); + cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_STRICT_SYMBOLIC_REF_CREATION, 1)); } void test_refs_create__symbolic(void) @@ -65,6 +66,54 @@ void test_refs_create__symbolic(void) git_reference_free(resolved_ref); } +void test_refs_create__symbolic_with_arbitrary_content(void) +{ + git_reference *new_reference, *looked_up_ref; + git_repository *repo2; + git_oid id; + + const char *new_head_tracker = "ANOTHER_HEAD_TRACKER"; + const char *arbitrary_target = "ARBITRARY DATA"; + + git_oid_fromstr(&id, current_master_tip); + + /* Attempt to create symbolic ref with arbitrary data in target + * fails by default + */ + cl_git_fail(git_reference_symbolic_create(&new_reference, g_repo, new_head_tracker, arbitrary_target, 0, NULL)); + + git_libgit2_opts(GIT_OPT_ENABLE_STRICT_SYMBOLIC_REF_CREATION, 0); + + /* With strict target validation disabled, ref creation succeeds */ + cl_git_pass(git_reference_symbolic_create(&new_reference, g_repo, new_head_tracker, arbitrary_target, 0, NULL)); + + /* Ensure the reference can be looked-up... */ + cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, new_head_tracker)); + cl_assert(git_reference_type(looked_up_ref) & GIT_REF_SYMBOLIC); + cl_assert(reference_is_packed(looked_up_ref) == 0); + cl_assert_equal_s(looked_up_ref->name, new_head_tracker); + + /* Ensure the target is what we expect it to be */ + cl_assert_equal_s(git_reference_symbolic_target(new_reference), arbitrary_target); + + /* Similar test with a fresh new repository object */ + cl_git_pass(git_repository_open(&repo2, "testrepo")); + + /* Ensure the reference can be looked-up... */ + cl_git_pass(git_reference_lookup(&looked_up_ref, repo2, new_head_tracker)); + cl_assert(git_reference_type(looked_up_ref) & GIT_REF_SYMBOLIC); + cl_assert(reference_is_packed(looked_up_ref) == 0); + cl_assert_equal_s(looked_up_ref->name, new_head_tracker); + + /* Ensure the target is what we expect it to be */ + cl_assert_equal_s(git_reference_symbolic_target(new_reference), arbitrary_target); + + git_repository_free(repo2); + git_reference_free(new_reference); + git_reference_free(looked_up_ref); + +} + void test_refs_create__deep_symbolic(void) { // create a deep symbolic reference From b84e58f45dea3aee35d0a6812669de36c9c9f3d1 Mon Sep 17 00:00:00 2001 From: Richard Ipsum Date: Sat, 25 Feb 2017 14:17:10 +0000 Subject: [PATCH 146/366] Whitespace and style fixes Use C style comments as per style guide, and fix mismatching indentation. --- tests/refs/create.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/refs/create.c b/tests/refs/create.c index 4196c7487..db6f8878d 100644 --- a/tests/refs/create.c +++ b/tests/refs/create.c @@ -12,12 +12,12 @@ static git_repository *g_repo; void test_refs_create__initialize(void) { - g_repo = cl_git_sandbox_init("testrepo"); + g_repo = cl_git_sandbox_init("testrepo"); } void test_refs_create__cleanup(void) { - cl_git_sandbox_cleanup(); + cl_git_sandbox_cleanup(); cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_STRICT_OBJECT_CREATION, 1)); cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_STRICT_SYMBOLIC_REF_CREATION, 1)); @@ -25,7 +25,7 @@ void test_refs_create__cleanup(void) void test_refs_create__symbolic(void) { - // create a new symbolic reference + /* create a new symbolic reference */ git_reference *new_reference, *looked_up_ref, *resolved_ref; git_repository *repo2; git_oid id; @@ -116,7 +116,7 @@ void test_refs_create__symbolic_with_arbitrary_content(void) void test_refs_create__deep_symbolic(void) { - // create a deep symbolic reference + /* create a deep symbolic reference */ git_reference *new_reference, *looked_up_ref, *resolved_ref; git_oid id; @@ -136,7 +136,7 @@ void test_refs_create__deep_symbolic(void) void test_refs_create__oid(void) { - // create a new OID reference + /* create a new OID reference */ git_reference *new_reference, *looked_up_ref; git_repository *repo2; git_oid id; From 4017017740d2f4ec9596fc3f79fc4b526f3bf06a Mon Sep 17 00:00:00 2001 From: Kevin Wojniak Date: Sat, 25 Feb 2017 10:21:59 -0800 Subject: [PATCH 147/366] Fix inet_pton tests triggering an assert in Haiku Haiku will assert in a nightly build if the "dst" input to inet_pton() is NULL. --- tests/core/posix.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/core/posix.c b/tests/core/posix.c index 26ae36049..018d0c8ba 100644 --- a/tests/core/posix.c +++ b/tests/core/posix.c @@ -94,10 +94,10 @@ void test_core_posix__inet_pton(void) cl_assert(p_inet_pton(AF_INET, "10.foo.bar.1", &addr) == 0); /* Test unsupported address families */ - cl_git_fail(p_inet_pton(12, "52.472", NULL)); /* AF_DECnet */ + cl_git_fail(p_inet_pton(12, "52.472", &addr)); /* AF_DECnet */ cl_assert_equal_i(EAFNOSUPPORT, errno); - cl_git_fail(p_inet_pton(5, "315.124", NULL)); /* AF_CHAOS */ + cl_git_fail(p_inet_pton(5, "315.124", &addr)); /* AF_CHAOS */ cl_assert_equal_i(EAFNOSUPPORT, errno); } From c1239e33273db65b09660ff0efd4b58df0e97af0 Mon Sep 17 00:00:00 2001 From: Patrick Blesi Date: Sat, 25 Feb 2017 23:09:42 -0600 Subject: [PATCH 148/366] Fix minor typos in CONVENTIONS.md --- CONVENTIONS.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONVENTIONS.md b/CONVENTIONS.md index 0be4b33cc..ffb696a4d 100644 --- a/CONVENTIONS.md +++ b/CONVENTIONS.md @@ -18,11 +18,11 @@ other's toes. - If a function returns an object as a return value, that function is a getter and the object's lifetime is tied to the parent object. Objects which are returned as the first argument as a - pointer-to-pointer are owned by the caller and it is repsponsible + pointer-to-pointer are owned by the caller and it is responsible for freeing it. Strings are returned via `git_buf` in order to allow for re-use and safe freeing. - - Most of what libgit2 does relates to I/O so you as a general rule + - Most of what libgit2 does relates to I/O so as a general rule you should assume that any function can fail due to errors as even getting data from the filesystem can result in all sorts of errors and complex failure cases. From 1255a9ac0c424d5fbf13ce166a8b0eef000e24e6 Mon Sep 17 00:00:00 2001 From: Richard Ipsum Date: Sun, 26 Feb 2017 13:34:13 +0000 Subject: [PATCH 149/366] Fix: make reflog include "(merge)" for merge commits This fixes issue #4094 --- src/refs.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/refs.c b/src/refs.c index 70f5519c6..0837dc4a8 100644 --- a/src/refs.c +++ b/src/refs.c @@ -1130,6 +1130,18 @@ int git_reference__update_terminal( return error; } +static const char *commit_type(const git_commit *commit) +{ + unsigned int count = git_commit_parentcount(commit); + + if (count >= 2) + return " (merge)"; + else if (count == 0) + return " (initial)"; + else + return ""; +} + int git_reference__update_for_commit( git_repository *repo, git_reference *ref, @@ -1146,7 +1158,7 @@ int git_reference__update_for_commit( if ((error = git_commit_lookup(&commit, repo, id)) < 0 || (error = git_buf_printf(&reflog_msg, "%s%s: %s", operation ? operation : "commit", - git_commit_parentcount(commit) == 0 ? " (initial)" : "", + commit_type(commit), git_commit_summary(commit))) < 0) goto done; From fc77891f6308ee4ca837cdf558969c5c457b1392 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Tue, 13 Dec 2016 10:07:42 -0500 Subject: [PATCH 150/366] git_filebuf: optionally fsync when committing --- src/filebuf.c | 8 ++++++++ src/filebuf.h | 4 +++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/filebuf.c b/src/filebuf.c index ef68b16f4..c4a13ffab 100644 --- a/src/filebuf.c +++ b/src/filebuf.c @@ -291,6 +291,9 @@ int git_filebuf_open_withsize(git_filebuf *file, const char *path, int flags, mo if (flags & GIT_FILEBUF_DO_NOT_BUFFER) file->do_not_buffer = true; + if (flags & GIT_FILEBUF_FSYNC) + file->do_fsync = true; + file->buf_size = size; file->buf_pos = 0; file->fd = -1; @@ -425,6 +428,11 @@ int git_filebuf_commit(git_filebuf *file) file->fd_is_open = false; + if (file->do_fsync && p_fsync(file->fd) < 0) { + giterr_set(GITERR_OS, "failed to fsync '%s'", file->path_lock); + goto on_error; + } + if (p_close(file->fd) < 0) { giterr_set(GITERR_OS, "failed to close file at '%s'", file->path_lock); goto on_error; diff --git a/src/filebuf.h b/src/filebuf.h index 467708d45..c65aea780 100644 --- a/src/filebuf.h +++ b/src/filebuf.h @@ -20,7 +20,8 @@ #define GIT_FILEBUF_FORCE (1 << 3) #define GIT_FILEBUF_TEMPORARY (1 << 4) #define GIT_FILEBUF_DO_NOT_BUFFER (1 << 5) -#define GIT_FILEBUF_DEFLATE_SHIFT (6) +#define GIT_FILEBUF_FSYNC (1 << 6) +#define GIT_FILEBUF_DEFLATE_SHIFT (7) #define GIT_FILELOCK_EXTENSION ".lock\0" #define GIT_FILELOCK_EXTLENGTH 6 @@ -47,6 +48,7 @@ struct git_filebuf { bool created_lock; bool did_rename; bool do_not_buffer; + bool do_fsync; int last_error; }; From fc27fe213c8462c8413486b8c2bfb82b25b3e7e6 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Tue, 13 Dec 2016 10:35:05 -0500 Subject: [PATCH 151/366] odb_loose: actually honor the fsync option We've had an fsync option for a long time, but it was "ignored". Stop ignoring it. --- include/git2/odb_backend.h | 2 +- src/odb_loose.c | 19 +++++++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/include/git2/odb_backend.h b/include/git2/odb_backend.h index b17cfd8ba..9199538ce 100644 --- a/include/git2/odb_backend.h +++ b/include/git2/odb_backend.h @@ -39,7 +39,7 @@ GIT_EXTERN(int) git_odb_backend_pack(git_odb_backend **out, const char *objects_ * @param out location to store the odb backend pointer * @param objects_dir the Git repository's objects directory * @param compression_level zlib compression level to use - * @param do_fsync whether to do an fsync() after writing (currently ignored) + * @param do_fsync whether to do an fsync() after writing * @param dir_mode permissions to use creating a directory or 0 for defaults * @param file_mode permissions to use creating a file or 0 for defaults * diff --git a/src/odb_loose.c b/src/odb_loose.c index b2e2f1fb7..8796f4bae 100644 --- a/src/odb_loose.c +++ b/src/odb_loose.c @@ -838,6 +838,17 @@ static void loose_backend__stream_free(git_odb_stream *_stream) git__free(stream); } +static int filebuf_flags(loose_backend *backend) +{ + int flags = GIT_FILEBUF_TEMPORARY | + (backend->object_zlib_level << GIT_FILEBUF_DEFLATE_SHIFT); + + if (backend->fsync_object_files) + flags |= GIT_FILEBUF_FSYNC; + + return flags; +} + static int loose_backend__stream(git_odb_stream **stream_out, git_odb_backend *_backend, git_off_t length, git_otype type) { loose_backend *backend; @@ -864,9 +875,7 @@ static int loose_backend__stream(git_odb_stream **stream_out, git_odb_backend *_ stream->stream.mode = GIT_STREAM_WRONLY; if (git_buf_joinpath(&tmp_path, backend->objects_dir, "tmp_object") < 0 || - git_filebuf_open(&stream->fbuf, tmp_path.ptr, - GIT_FILEBUF_TEMPORARY | - (backend->object_zlib_level << GIT_FILEBUF_DEFLATE_SHIFT), + git_filebuf_open(&stream->fbuf, tmp_path.ptr, filebuf_flags(backend), backend->object_file_mode) < 0 || stream->stream.write((git_odb_stream *)stream, hdr, hdrlen) < 0) { @@ -894,9 +903,7 @@ static int loose_backend__write(git_odb_backend *_backend, const git_oid *oid, c header_len = git_odb__format_object_header(header, sizeof(header), len, type); if (git_buf_joinpath(&final_path, backend->objects_dir, "tmp_object") < 0 || - git_filebuf_open(&fbuf, final_path.ptr, - GIT_FILEBUF_TEMPORARY | - (backend->object_zlib_level << GIT_FILEBUF_DEFLATE_SHIFT), + git_filebuf_open(&fbuf, final_path.ptr, filebuf_flags(backend), backend->object_file_mode) < 0) { error = -1; From 6d3ad7e09ee4b101e8e68f38783e3e4139bc2691 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Tue, 13 Dec 2016 10:58:43 -0500 Subject: [PATCH 152/366] Add `ENABLE_SYNCHRONIZED_OBJECT_CREATION` option Allow users to enable `SYNCHRONIZED_OBJECT_CREATION` with a setting. --- include/git2/common.h | 8 ++++++++ src/object.c | 1 + src/object.h | 1 + src/odb_loose.c | 3 ++- src/settings.c | 4 ++++ 5 files changed, 16 insertions(+), 1 deletion(-) diff --git a/include/git2/common.h b/include/git2/common.h index f13dfd509..f5d37ede4 100644 --- a/include/git2/common.h +++ b/include/git2/common.h @@ -179,6 +179,7 @@ typedef enum { GIT_OPT_SET_SSL_CIPHERS, GIT_OPT_GET_USER_AGENT, GIT_OPT_ENABLE_OFS_DELTA, + GIT_OPT_ENABLE_SYNCHRONIZED_OBJECT_CREATION, } git_libgit2_opt_t; /** @@ -316,6 +317,13 @@ typedef enum { * > Packfiles containing offset deltas can still be read. * > This defaults to enabled. * + * * opts(GIT_OPT_ENABLE_SYNCHRONIZED_OBJECT_CREATION, int enabled) + * + * > Enable synchronized writes of new objects using `fsync` + * > (or the platform equivalent) to ensure that new object data + * > is written to permanent storage, not simply cached. This + * > defaults to disabled. + * * @param option Option key * @param ... value to set the option * @return 0 on success, <0 on failure diff --git a/src/object.c b/src/object.c index 2da36a2ee..c92adbbea 100644 --- a/src/object.c +++ b/src/object.c @@ -16,6 +16,7 @@ #include "tag.h" bool git_object__strict_input_validation = true; +bool git_object__synchronized_writing = false; typedef struct { const char *str; /* type name string */ diff --git a/src/object.h b/src/object.h index dd227d16d..7d94d8bcd 100644 --- a/src/object.h +++ b/src/object.h @@ -10,6 +10,7 @@ #include "repository.h" extern bool git_object__strict_input_validation; +extern bool git_object__synchronized_writing; /** Base git object for inheritance */ struct git_object { diff --git a/src/odb_loose.c b/src/odb_loose.c index 8796f4bae..5a80b7a4b 100644 --- a/src/odb_loose.c +++ b/src/odb_loose.c @@ -14,6 +14,7 @@ #include "odb.h" #include "delta.h" #include "filebuf.h" +#include "object.h" #include "git2/odb_backend.h" #include "git2/types.h" @@ -843,7 +844,7 @@ static int filebuf_flags(loose_backend *backend) int flags = GIT_FILEBUF_TEMPORARY | (backend->object_zlib_level << GIT_FILEBUF_DEFLATE_SHIFT); - if (backend->fsync_object_files) + if (backend->fsync_object_files || git_object__synchronized_writing) flags |= GIT_FILEBUF_FSYNC; return flags; diff --git a/src/settings.c b/src/settings.c index 21585672c..f3120ff57 100644 --- a/src/settings.c +++ b/src/settings.c @@ -227,6 +227,10 @@ int git_libgit2_opts(int key, ...) git_smart__ofs_delta_enabled = (va_arg(ap, int) != 0); break; + case GIT_OPT_ENABLE_SYNCHRONIZED_OBJECT_CREATION: + git_object__synchronized_writing = (va_arg(ap, int) != 0); + break; + default: giterr_set(GITERR_INVALID, "invalid option key"); error = -1; From e6ed0d2f03625f5d6b60db54fc894902d7ddbc32 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Tue, 13 Dec 2016 11:31:38 -0500 Subject: [PATCH 153/366] odb_loose: fsync tests Introduce a simple counter that `p_fsync` implements. This is useful for ensuring that `p_fsync` is called when we expect it to be, for example when we have enabled an odb backend to perform `fsync`s when writing objects. --- src/posix.c | 2 ++ src/posix.h | 6 ++++++ src/unix/posix.h | 7 ++++++- src/win32/posix_w32.c | 2 ++ tests/odb/loose.c | 34 ++++++++++++++++++++++++++++++++++ 5 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/posix.c b/src/posix.c index e68f324f6..94deb6ab0 100644 --- a/src/posix.c +++ b/src/posix.c @@ -10,6 +10,8 @@ #include #include +size_t p_fsync__cnt = 0; + #ifndef GIT_WIN32 #ifdef NO_ADDRINFO diff --git a/src/posix.h b/src/posix.h index f204751cf..bd5a98e26 100644 --- a/src/posix.h +++ b/src/posix.h @@ -111,6 +111,12 @@ extern int p_rename(const char *from, const char *to); extern int git__page_size(size_t *page_size); extern int git__mmap_alignment(size_t *page_size); +/* The number of times `p_fsync` has been called. Note that this is for + * test code only; it it not necessarily thread-safe and should not be + * relied upon in production. + */ +extern size_t p_fsync__cnt; + /** * Platform-dependent methods */ diff --git a/src/unix/posix.h b/src/unix/posix.h index b4786403f..52985fd8a 100644 --- a/src/unix/posix.h +++ b/src/unix/posix.h @@ -40,9 +40,14 @@ typedef int GIT_SOCKET; #define p_link(o,n) link(o, n) #define p_unlink(p) unlink(p) #define p_mkdir(p,m) mkdir(p, m) -#define p_fsync(fd) fsync(fd) extern char *p_realpath(const char *, char *); +GIT_INLINE(int) p_fsync(int fd) +{ + p_fsync__cnt++; + return fsync(fd); +} + #define p_recv(s,b,l,f) recv(s,b,l,f) #define p_send(s,b,l,f) send(s,b,l,f) #define p_inet_pton(a, b, c) inet_pton(a, b, c) diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c index fea634b00..5172627b0 100644 --- a/src/win32/posix_w32.c +++ b/src/win32/posix_w32.c @@ -113,6 +113,8 @@ int p_fsync(int fd) { HANDLE fh = (HANDLE)_get_osfhandle(fd); + p_fsync__cnt++; + if (fh == INVALID_HANDLE_VALUE) { errno = EBADF; return -1; diff --git a/tests/odb/loose.c b/tests/odb/loose.c index c91927c4a..43dabcb0c 100644 --- a/tests/odb/loose.c +++ b/tests/odb/loose.c @@ -56,11 +56,13 @@ static void test_read_object(object_data *data) void test_odb_loose__initialize(void) { + p_fsync__cnt = 0; cl_must_pass(p_mkdir("test-objects", GIT_OBJECT_DIR_MODE)); } void test_odb_loose__cleanup(void) { + cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SYNCHRONIZED_OBJECT_CREATION, 0)); cl_fixture_cleanup("test-objects"); } @@ -150,3 +152,35 @@ void test_odb_loose__permissions_readwrite(void) { test_write_object_permission(0777, 0666, 0777, 0666); } + +static void write_object_to_loose_odb(int fsync) +{ + git_odb *odb; + git_odb_backend *backend; + git_oid oid; + + cl_git_pass(git_odb_new(&odb)); + cl_git_pass(git_odb_backend_loose(&backend, "test-objects", -1, fsync, 0777, 0666)); + cl_git_pass(git_odb_add_backend(odb, backend, 1)); + cl_git_pass(git_odb_write(&oid, odb, "Test data\n", 10, GIT_OBJ_BLOB)); + git_odb_free(odb); +} + +void test_odb_loose__does_not_fsync_by_default(void) +{ + write_object_to_loose_odb(0); + cl_assert_equal_sz(0, p_fsync__cnt); +} + +void test_odb_loose__fsync_obeys_odb_option(void) +{ + write_object_to_loose_odb(1); + cl_assert(p_fsync__cnt > 0); +} + +void test_odb_loose__fsync_obeys_global_setting(void) +{ + cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SYNCHRONIZED_OBJECT_CREATION, 1)); + write_object_to_loose_odb(0); + cl_assert(p_fsync__cnt > 0); +} From 1c2c0ae2a4d09f5b0de3c4c091c5a93ab34baa46 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Wed, 14 Dec 2016 12:51:40 -0500 Subject: [PATCH 154/366] packbuilder: honor git_object__synchronized_writing Honor `git_object__synchronized_writing` when creating a packfile and corresponding index. --- src/indexer.c | 10 +++++++++- tests/pack/packbuilder.c | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/indexer.c b/src/indexer.c index 869e2299f..30c365565 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -17,6 +17,7 @@ #include "oid.h" #include "oidmap.h" #include "zstream.h" +#include "object.h" extern git_mutex git__mwindow_mutex; @@ -989,7 +990,9 @@ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats) return -1; if (git_filebuf_open(&index_file, filename.ptr, - GIT_FILEBUF_HASH_CONTENTS, idx->mode) < 0) + GIT_FILEBUF_HASH_CONTENTS | + (git_object__synchronized_writing ? GIT_FILEBUF_FSYNC : 0), + idx->mode) < 0) goto on_error; /* Write out the header */ @@ -1066,6 +1069,11 @@ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats) return -1; } + if (git_object__synchronized_writing && p_fsync(idx->pack->mwf.fd) < 0) { + giterr_set(GITERR_OS, "failed to fsync packfile"); + goto on_error; + } + /* We need to close the descriptor here so Windows doesn't choke on commit_at */ if (p_close(idx->pack->mwf.fd) < 0) { giterr_set(GITERR_OS, "failed to close packfile"); diff --git a/tests/pack/packbuilder.c b/tests/pack/packbuilder.c index 29f3e2d64..9afc178b3 100644 --- a/tests/pack/packbuilder.c +++ b/tests/pack/packbuilder.c @@ -23,6 +23,7 @@ void test_pack_packbuilder__initialize(void) cl_git_pass(git_vector_init(&_commits, 0, NULL)); _commits_is_initialized = 1; memset(&_stats, 0, sizeof(_stats)); + p_fsync__cnt = 0; } void test_pack_packbuilder__cleanup(void) @@ -30,6 +31,8 @@ void test_pack_packbuilder__cleanup(void) git_oid *o; unsigned int i; + cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SYNCHRONIZED_OBJECT_CREATION, 0)); + if (_commits_is_initialized) { _commits_is_initialized = 0; git_vector_foreach(&_commits, i, o) { @@ -188,6 +191,22 @@ void test_pack_packbuilder__permissions_readwrite(void) test_write_pack_permission(0666, 0666); } +void test_pack_packbuilder__does_not_fsync_by_default(void) +{ + seed_packbuilder(); + git_packbuilder_write(_packbuilder, ".", 0666, NULL, NULL); + cl_assert_equal_sz(0, p_fsync__cnt); +} + +void test_pack_packbuilder__fsync_when_asked(void) +{ + cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SYNCHRONIZED_OBJECT_CREATION, 1)); + p_fsync__cnt = 0; + seed_packbuilder(); + git_packbuilder_write(_packbuilder, ".", 0666, NULL, NULL); + cl_assert_equal_sz(2, p_fsync__cnt); +} + static int foreach_cb(void *buf, size_t len, void *payload) { git_indexer *idx = (git_indexer *) payload; From 5312621bd4dc0ba38866db3311462139b2eb8e60 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 15 Dec 2016 10:51:02 -0600 Subject: [PATCH 155/366] git_futils_writebuffer: optionally fsync Add a custom `O_FSYNC` bit (if it's not been defined by the operating system`) so that `git_futils_writebuffer` can optionally do an `fsync` when it's done writing. We call `fsync` ourselves, even on systems that define `O_FSYNC` because its definition is no guarantee of its actual support. Mac, for instance, defines it but doesn't support it in an `open(2)` call. --- src/fileops.c | 14 +++++++++++++- src/fileops.h | 7 +++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/fileops.c b/src/fileops.c index 57dea8fce..ffa692eed 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -235,10 +235,16 @@ int git_futils_readbuffer(git_buf *buf, const char *path) int git_futils_writebuffer( const git_buf *buf, const char *path, int flags, mode_t mode) { - int fd, error = 0; + int fd, do_fsync = 0, error = 0; + + if ((flags & O_FSYNC) != 0) + do_fsync = 1; + + flags &= ~O_FSYNC; if (flags <= 0) flags = O_CREAT | O_TRUNC | O_WRONLY; + if (!mode) mode = GIT_FILEMODE_BLOB; @@ -253,6 +259,12 @@ int git_futils_writebuffer( return error; } + if (do_fsync && (error = p_fsync(fd)) < 0) { + giterr_set(GITERR_OS, "could not fsync '%s'", path); + p_close(fd); + return error; + } + if ((error = p_close(fd)) < 0) giterr_set(GITERR_OS, "error while closing '%s'", path); diff --git a/src/fileops.h b/src/fileops.h index 65c96a6f5..9a6fc3f6b 100644 --- a/src/fileops.h +++ b/src/fileops.h @@ -25,6 +25,13 @@ extern int git_futils_readbuffer_updated( git_buf *obj, const char *path, git_oid *checksum, int *updated); extern int git_futils_readbuffer_fd(git_buf *obj, git_file fd, size_t len); +/* Additional constants for `git_futils_writebuffer`'s `open_flags`. We + * support these internally and they will be removed before the `open` call. + */ +#ifndef O_FSYNC +# define O_FSYNC (1 << 31) +#endif + extern int git_futils_writebuffer( const git_buf *buf, const char *path, int open_flags, mode_t mode); From af3dcb0e50416ce08bcfed7524b073b980180ef2 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 15 Dec 2016 10:56:52 -0600 Subject: [PATCH 156/366] refdb_fs: optionally fsync loose references --- src/refdb_fs.c | 17 +++++++++++++---- tests/refs/create.c | 27 +++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/src/refdb_fs.c b/src/refdb_fs.c index e2a69d6ed..11ff96843 100644 --- a/src/refdb_fs.c +++ b/src/refdb_fs.c @@ -736,7 +736,7 @@ static int reference_path_available( static int loose_lock(git_filebuf *file, refdb_fs_backend *backend, const char *name) { - int error; + int error, filebuf_flags; git_buf ref_path = GIT_BUF_INIT; assert(file && backend && name); @@ -755,7 +755,11 @@ static int loose_lock(git_filebuf *file, refdb_fs_backend *backend, const char * if (git_buf_joinpath(&ref_path, backend->gitpath, name) < 0) return -1; - error = git_filebuf_open(file, ref_path.ptr, GIT_FILEBUF_FORCE, GIT_REFS_FILE_MODE); + filebuf_flags = GIT_FILEBUF_FORCE; + if (git_object__synchronized_writing) + filebuf_flags |= GIT_FILEBUF_FSYNC; + + error = git_filebuf_open(file, ref_path.ptr, filebuf_flags, GIT_REFS_FILE_MODE); if (error == GIT_EDIRECTORY) giterr_set(GITERR_REFERENCE, "cannot lock ref '%s', there are refs beneath that folder", name); @@ -1784,7 +1788,7 @@ success: /* Append to the reflog, must be called under reference lock */ static int reflog_append(refdb_fs_backend *backend, const git_reference *ref, const git_oid *old, const git_oid *new, const git_signature *who, const char *message) { - int error, is_symbolic; + int error, is_symbolic, open_flags; git_oid old_id = {{0}}, new_id = {{0}}; git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT; git_repository *repo = backend->repo; @@ -1852,7 +1856,12 @@ static int reflog_append(refdb_fs_backend *backend, const git_reference *ref, co goto cleanup; } - error = git_futils_writebuffer(&buf, git_buf_cstr(&path), O_WRONLY|O_CREAT|O_APPEND, GIT_REFLOG_FILE_MODE); + open_flags = O_WRONLY | O_CREAT | O_APPEND; + + if (git_object__synchronized_writing) + open_flags |= O_FSYNC; + + error = git_futils_writebuffer(&buf, git_buf_cstr(&path), open_flags, GIT_REFLOG_FILE_MODE); cleanup: git_buf_free(&buf); diff --git a/tests/refs/create.c b/tests/refs/create.c index db6f8878d..1189c47f3 100644 --- a/tests/refs/create.c +++ b/tests/refs/create.c @@ -13,6 +13,7 @@ static git_repository *g_repo; void test_refs_create__initialize(void) { g_repo = cl_git_sandbox_init("testrepo"); + p_fsync__cnt = 0; } void test_refs_create__cleanup(void) @@ -21,6 +22,7 @@ void test_refs_create__cleanup(void) cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_STRICT_OBJECT_CREATION, 1)); cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_STRICT_SYMBOLIC_REF_CREATION, 1)); + cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SYNCHRONIZED_OBJECT_CREATION, 0)); } void test_refs_create__symbolic(void) @@ -297,3 +299,28 @@ void test_refs_create__creating_a_loose_ref_with_invalid_windows_name(void) test_win32_name("refs/heads/com1"); } + +void test_refs_create__does_not_fsync_by_default(void) +{ + git_reference *ref = NULL; + git_oid id; + + git_oid_fromstr(&id, current_master_tip); + cl_git_pass(git_reference_create(&ref, g_repo, "refs/heads/fsync_test", &id, 0, "log message")); + git_reference_free(ref); + cl_assert_equal_i(0, p_fsync__cnt); +} + +void test_refs_create__fsyncs_when_requested(void) +{ + git_reference *ref = NULL; + git_oid id; + + cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SYNCHRONIZED_OBJECT_CREATION, 1)); + p_fsync__cnt = 0; + + git_oid_fromstr(&id, current_master_tip); + cl_git_pass(git_reference_create(&ref, g_repo, "refs/heads/fsync_test", &id, 0, "log message")); + git_reference_free(ref); + cl_assert_equal_i(2, p_fsync__cnt); +} From eb56ed81afd0091a0616a1099d7792f12e0726f6 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 15 Dec 2016 14:49:43 -0600 Subject: [PATCH 157/366] refdb_fs: optionally fsync packed refs --- src/refdb_fs.c | 7 +++++-- tests/refs/create.c | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/refdb_fs.c b/src/refdb_fs.c index 11ff96843..fac5ba5d1 100644 --- a/src/refdb_fs.c +++ b/src/refdb_fs.c @@ -994,15 +994,18 @@ static int packed_write(refdb_fs_backend *backend) { git_sortedcache *refcache = backend->refcache; git_filebuf pack_file = GIT_FILEBUF_INIT; - int error; + int error, open_flags = 0; size_t i; /* lock the cache to updates while we do this */ if ((error = git_sortedcache_wlock(refcache)) < 0) return error; + if (git_object__synchronized_writing) + open_flags = GIT_FILEBUF_FSYNC; + /* Open the file! */ - if ((error = git_filebuf_open(&pack_file, git_sortedcache_path(refcache), 0, GIT_PACKEDREFS_FILE_MODE)) < 0) + if ((error = git_filebuf_open(&pack_file, git_sortedcache_path(refcache), open_flags, GIT_PACKEDREFS_FILE_MODE)) < 0) goto fail; /* Packfiles have a header... apparently diff --git a/tests/refs/create.c b/tests/refs/create.c index 1189c47f3..5c46fb3c2 100644 --- a/tests/refs/create.c +++ b/tests/refs/create.c @@ -303,17 +303,24 @@ void test_refs_create__creating_a_loose_ref_with_invalid_windows_name(void) void test_refs_create__does_not_fsync_by_default(void) { git_reference *ref = NULL; + git_refdb *refdb; git_oid id; git_oid_fromstr(&id, current_master_tip); cl_git_pass(git_reference_create(&ref, g_repo, "refs/heads/fsync_test", &id, 0, "log message")); git_reference_free(ref); + + cl_git_pass(git_repository_refdb(&refdb, g_repo)); + cl_git_pass(git_refdb_compress(refdb)); + git_refdb_free(refdb); + cl_assert_equal_i(0, p_fsync__cnt); } void test_refs_create__fsyncs_when_requested(void) { git_reference *ref = NULL; + git_refdb *refdb; git_oid id; cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SYNCHRONIZED_OBJECT_CREATION, 1)); @@ -323,4 +330,12 @@ void test_refs_create__fsyncs_when_requested(void) cl_git_pass(git_reference_create(&ref, g_repo, "refs/heads/fsync_test", &id, 0, "log message")); git_reference_free(ref); cl_assert_equal_i(2, p_fsync__cnt); + + p_fsync__cnt = 0; + + cl_git_pass(git_repository_refdb(&refdb, g_repo)); + cl_git_pass(git_refdb_compress(refdb)); + git_refdb_free(refdb); + + cl_assert_equal_i(1, p_fsync__cnt); } From 5a747e0c6c5170d29969eb15822c36d76dd3e4ac Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Tue, 27 Dec 2016 23:07:07 +0000 Subject: [PATCH 158/366] git_futils_writebuffer: default only when flags==0 Only use defaults for `git_futils_writebuffer` when flags == 0, lest (1 << 31) be treated as the defaults. --- src/fileops.c | 6 +++--- src/rebase.c | 18 +++++++++--------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/fileops.c b/src/fileops.c index ffa692eed..13b1fc2a1 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -237,14 +237,14 @@ int git_futils_writebuffer( { int fd, do_fsync = 0, error = 0; + if (!flags) + flags = O_CREAT | O_TRUNC | O_WRONLY; + if ((flags & O_FSYNC) != 0) do_fsync = 1; flags &= ~O_FSYNC; - if (flags <= 0) - flags = O_CREAT | O_TRUNC | O_WRONLY; - if (!mode) mode = GIT_FILEMODE_BLOB; diff --git a/src/rebase.c b/src/rebase.c index 09941a2a2..f91a635b2 100644 --- a/src/rebase.c +++ b/src/rebase.c @@ -447,8 +447,8 @@ static int rebase_setupfiles_merge(git_rebase *rebase) size_t i; int error = 0; - if ((error = rebase_setupfile(rebase, END_FILE, -1, "%" PRIuZ "\n", git_array_size(rebase->operations))) < 0 || - (error = rebase_setupfile(rebase, ONTO_NAME_FILE, -1, "%s\n", rebase->onto_name)) < 0) + if ((error = rebase_setupfile(rebase, END_FILE, 0, "%" PRIuZ "\n", git_array_size(rebase->operations))) < 0 || + (error = rebase_setupfile(rebase, ONTO_NAME_FILE, 0, "%s\n", rebase->onto_name)) < 0) goto done; for (i = 0; i < git_array_size(rebase->operations); i++) { @@ -459,7 +459,7 @@ static int rebase_setupfiles_merge(git_rebase *rebase) git_oid_fmt(id_str, &operation->id); - if ((error = rebase_setupfile(rebase, commit_filename.ptr, -1, + if ((error = rebase_setupfile(rebase, commit_filename.ptr, 0, "%.*s\n", GIT_OID_HEXSZ, id_str)) < 0) goto done; } @@ -486,10 +486,10 @@ static int rebase_setupfiles(git_rebase *rebase) rebase->orig_head_name; if (git_repository__set_orig_head(rebase->repo, &rebase->orig_head_id) < 0 || - rebase_setupfile(rebase, HEAD_NAME_FILE, -1, "%s\n", orig_head_name) < 0 || - rebase_setupfile(rebase, ONTO_FILE, -1, "%.*s\n", GIT_OID_HEXSZ, onto) < 0 || - rebase_setupfile(rebase, ORIG_HEAD_FILE, -1, "%.*s\n", GIT_OID_HEXSZ, orig_head) < 0 || - rebase_setupfile(rebase, QUIET_FILE, -1, rebase->quiet ? "t\n" : "\n") < 0) + rebase_setupfile(rebase, HEAD_NAME_FILE, 0, "%s\n", orig_head_name) < 0 || + rebase_setupfile(rebase, ONTO_FILE, 0, "%.*s\n", GIT_OID_HEXSZ, onto) < 0 || + rebase_setupfile(rebase, ORIG_HEAD_FILE, 0, "%.*s\n", GIT_OID_HEXSZ, orig_head) < 0 || + rebase_setupfile(rebase, QUIET_FILE, 0, rebase->quiet ? "t\n" : "\n") < 0) return -1; return rebase_setupfiles_merge(rebase); @@ -821,8 +821,8 @@ static int rebase_next_merge( normalize_checkout_options_for_apply(&checkout_opts, rebase, current_commit); if ((error = git_indexwriter_init_for_operation(&indexwriter, rebase->repo, &checkout_opts.checkout_strategy)) < 0 || - (error = rebase_setupfile(rebase, MSGNUM_FILE, -1, "%" PRIuZ "\n", rebase->current+1)) < 0 || - (error = rebase_setupfile(rebase, CURRENT_FILE, -1, "%.*s\n", GIT_OID_HEXSZ, current_idstr)) < 0 || + (error = rebase_setupfile(rebase, MSGNUM_FILE, 0, "%" PRIuZ "\n", rebase->current+1)) < 0 || + (error = rebase_setupfile(rebase, CURRENT_FILE, 0, "%.*s\n", GIT_OID_HEXSZ, current_idstr)) < 0 || (error = git_merge_trees(&index, rebase->repo, parent_tree, head_tree, current_tree, &rebase->options.merge_options)) < 0 || (error = git_merge__check_result(rebase->repo, index)) < 0 || (error = git_checkout_index(rebase->repo, index, &checkout_opts)) < 0 || From 1229e1c4d7ea1eb4c5bcd5c0d89bc576053175db Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 17 Feb 2017 16:36:53 +0000 Subject: [PATCH 159/366] fsync parent directories when fsyncing When fsync'ing files, fsync the parent directory in the case where we rename a file into place, or create a new file, to ensure that the directory entry is flushed correctly. --- src/filebuf.c | 3 +++ src/fileops.c | 32 +++++++++++++++++++++++++++++++- src/fileops.h | 18 ++++++++++++++++++ src/indexer.c | 9 ++++++++- tests/pack/packbuilder.c | 2 +- tests/refs/create.c | 4 ++-- 6 files changed, 63 insertions(+), 5 deletions(-) diff --git a/src/filebuf.c b/src/filebuf.c index c4a13ffab..f37cf02b4 100644 --- a/src/filebuf.c +++ b/src/filebuf.c @@ -445,6 +445,9 @@ int git_filebuf_commit(git_filebuf *file) goto on_error; } + if (file->do_fsync && git_futils_fsync_parent(file->path_original) < 0) + goto on_error; + file->did_rename = true; git_filebuf_cleanup(file); diff --git a/src/fileops.c b/src/fileops.c index 13b1fc2a1..881d1bed4 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -265,8 +265,13 @@ int git_futils_writebuffer( return error; } - if ((error = p_close(fd)) < 0) + if ((error = p_close(fd)) < 0) { giterr_set(GITERR_OS, "error while closing '%s'", path); + return error; + } + + if (do_fsync && (flags & O_CREAT)) + error = git_futils_fsync_parent(path); return error; } @@ -1119,3 +1124,28 @@ void git_futils_filestamp_set_from_stat( memset(stamp, 0, sizeof(*stamp)); } } + +int git_futils_fsync_dir(const char *path) +{ + int fd, error = -1; + + if ((fd = p_open(path, O_RDONLY)) < 0) { + giterr_set(GITERR_OS, "failed to open directory '%s' for fsync", path); + return -1; + } + + if ((error = p_fsync(fd)) < 0) + giterr_set(GITERR_OS, "failed to fsync directory '%s'", path); + + p_close(fd); + return error; +} + +int git_futils_fsync_parent(const char *path) +{ + char *parent = git_path_dirname(path); + int error = git_futils_fsync_dir(parent); + + git__free(parent); + return error; +} diff --git a/src/fileops.h b/src/fileops.h index 9a6fc3f6b..46886b0d7 100644 --- a/src/fileops.h +++ b/src/fileops.h @@ -363,4 +363,22 @@ extern void git_futils_filestamp_set( extern void git_futils_filestamp_set_from_stat( git_futils_filestamp *stamp, struct stat *st); +/** + * `fsync` the parent directory of the given path, if `fsync` is + * supported for directories on this platform. + * + * @param path Path of the directory to sync. + * @return 0 on success, -1 on error + */ +extern int git_futils_fsync_dir(const char *path); + +/** + * `fsync` the parent directory of the given path, if `fsync` is + * supported for directories on this platform. + * + * @param path Path of the file whose parent directory should be synced. + * @return 0 on success, -1 on error + */ +extern int git_futils_fsync_parent(const char *path); + #endif /* INCLUDE_fileops_h__ */ diff --git a/src/indexer.c b/src/indexer.c index 30c365565..9510253b5 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -1086,7 +1086,14 @@ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats) goto on_error; /* And don't forget to rename the packfile to its new place. */ - p_rename(idx->pack->pack_name, git_buf_cstr(&filename)); + if (p_rename(idx->pack->pack_name, git_buf_cstr(&filename)) < 0) + goto on_error; + + /* And fsync the parent directory if we're asked to. */ + if (git_object__synchronized_writing && + git_futils_fsync_parent(git_buf_cstr(&filename)) < 0) + goto on_error; + idx->pack_committed = 1; git_buf_free(&filename); diff --git a/tests/pack/packbuilder.c b/tests/pack/packbuilder.c index 9afc178b3..77f61f79b 100644 --- a/tests/pack/packbuilder.c +++ b/tests/pack/packbuilder.c @@ -204,7 +204,7 @@ void test_pack_packbuilder__fsync_when_asked(void) p_fsync__cnt = 0; seed_packbuilder(); git_packbuilder_write(_packbuilder, ".", 0666, NULL, NULL); - cl_assert_equal_sz(2, p_fsync__cnt); + cl_assert_equal_sz(4, p_fsync__cnt); } static int foreach_cb(void *buf, size_t len, void *payload) diff --git a/tests/refs/create.c b/tests/refs/create.c index 5c46fb3c2..e9630e853 100644 --- a/tests/refs/create.c +++ b/tests/refs/create.c @@ -329,7 +329,7 @@ void test_refs_create__fsyncs_when_requested(void) git_oid_fromstr(&id, current_master_tip); cl_git_pass(git_reference_create(&ref, g_repo, "refs/heads/fsync_test", &id, 0, "log message")); git_reference_free(ref); - cl_assert_equal_i(2, p_fsync__cnt); + cl_assert_equal_i(4, p_fsync__cnt); p_fsync__cnt = 0; @@ -337,5 +337,5 @@ void test_refs_create__fsyncs_when_requested(void) cl_git_pass(git_refdb_compress(refdb)); git_refdb_free(refdb); - cl_assert_equal_i(1, p_fsync__cnt); + cl_assert_equal_i(2, p_fsync__cnt); } From 2a5ad7d0f2c28337530855fae250f85123070fcb Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 17 Feb 2017 16:42:40 +0000 Subject: [PATCH 160/366] fsync: call it "synchronous" object writing Rename `GIT_OPT_ENABLE_SYNCHRONIZED_OBJECT_CREATION` -> `GIT_OPT_ENABLE_SYNCHRONOUS_OBJECT_CREATION`. --- include/git2/common.h | 4 ++-- src/indexer.c | 6 +++--- src/object.c | 2 +- src/object.h | 2 +- src/odb_loose.c | 2 +- src/refdb_fs.c | 6 +++--- src/settings.c | 4 ++-- tests/odb/loose.c | 4 ++-- tests/pack/packbuilder.c | 4 ++-- tests/refs/create.c | 4 ++-- 10 files changed, 19 insertions(+), 19 deletions(-) diff --git a/include/git2/common.h b/include/git2/common.h index f5d37ede4..c909f86ca 100644 --- a/include/git2/common.h +++ b/include/git2/common.h @@ -179,7 +179,7 @@ typedef enum { GIT_OPT_SET_SSL_CIPHERS, GIT_OPT_GET_USER_AGENT, GIT_OPT_ENABLE_OFS_DELTA, - GIT_OPT_ENABLE_SYNCHRONIZED_OBJECT_CREATION, + GIT_OPT_ENABLE_SYNCHRONOUS_OBJECT_CREATION, } git_libgit2_opt_t; /** @@ -317,7 +317,7 @@ typedef enum { * > Packfiles containing offset deltas can still be read. * > This defaults to enabled. * - * * opts(GIT_OPT_ENABLE_SYNCHRONIZED_OBJECT_CREATION, int enabled) + * * opts(GIT_OPT_ENABLE_SYNCHRONOUS_OBJECT_CREATION, int enabled) * * > Enable synchronized writes of new objects using `fsync` * > (or the platform equivalent) to ensure that new object data diff --git a/src/indexer.c b/src/indexer.c index 9510253b5..3fd7223e5 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -991,7 +991,7 @@ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats) if (git_filebuf_open(&index_file, filename.ptr, GIT_FILEBUF_HASH_CONTENTS | - (git_object__synchronized_writing ? GIT_FILEBUF_FSYNC : 0), + (git_object__synchronous_writing ? GIT_FILEBUF_FSYNC : 0), idx->mode) < 0) goto on_error; @@ -1069,7 +1069,7 @@ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats) return -1; } - if (git_object__synchronized_writing && p_fsync(idx->pack->mwf.fd) < 0) { + if (git_object__synchronous_writing && p_fsync(idx->pack->mwf.fd) < 0) { giterr_set(GITERR_OS, "failed to fsync packfile"); goto on_error; } @@ -1090,7 +1090,7 @@ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats) goto on_error; /* And fsync the parent directory if we're asked to. */ - if (git_object__synchronized_writing && + if (git_object__synchronous_writing && git_futils_fsync_parent(git_buf_cstr(&filename)) < 0) goto on_error; diff --git a/src/object.c b/src/object.c index c92adbbea..bd87c9310 100644 --- a/src/object.c +++ b/src/object.c @@ -16,7 +16,7 @@ #include "tag.h" bool git_object__strict_input_validation = true; -bool git_object__synchronized_writing = false; +bool git_object__synchronous_writing = false; typedef struct { const char *str; /* type name string */ diff --git a/src/object.h b/src/object.h index 7d94d8bcd..13117e4c3 100644 --- a/src/object.h +++ b/src/object.h @@ -10,7 +10,7 @@ #include "repository.h" extern bool git_object__strict_input_validation; -extern bool git_object__synchronized_writing; +extern bool git_object__synchronous_writing; /** Base git object for inheritance */ struct git_object { diff --git a/src/odb_loose.c b/src/odb_loose.c index 5a80b7a4b..e14af4fab 100644 --- a/src/odb_loose.c +++ b/src/odb_loose.c @@ -844,7 +844,7 @@ static int filebuf_flags(loose_backend *backend) int flags = GIT_FILEBUF_TEMPORARY | (backend->object_zlib_level << GIT_FILEBUF_DEFLATE_SHIFT); - if (backend->fsync_object_files || git_object__synchronized_writing) + if (backend->fsync_object_files || git_object__synchronous_writing) flags |= GIT_FILEBUF_FSYNC; return flags; diff --git a/src/refdb_fs.c b/src/refdb_fs.c index fac5ba5d1..d7a458a87 100644 --- a/src/refdb_fs.c +++ b/src/refdb_fs.c @@ -756,7 +756,7 @@ static int loose_lock(git_filebuf *file, refdb_fs_backend *backend, const char * return -1; filebuf_flags = GIT_FILEBUF_FORCE; - if (git_object__synchronized_writing) + if (git_object__synchronous_writing) filebuf_flags |= GIT_FILEBUF_FSYNC; error = git_filebuf_open(file, ref_path.ptr, filebuf_flags, GIT_REFS_FILE_MODE); @@ -1001,7 +1001,7 @@ static int packed_write(refdb_fs_backend *backend) if ((error = git_sortedcache_wlock(refcache)) < 0) return error; - if (git_object__synchronized_writing) + if (git_object__synchronous_writing) open_flags = GIT_FILEBUF_FSYNC; /* Open the file! */ @@ -1861,7 +1861,7 @@ static int reflog_append(refdb_fs_backend *backend, const git_reference *ref, co open_flags = O_WRONLY | O_CREAT | O_APPEND; - if (git_object__synchronized_writing) + if (git_object__synchronous_writing) open_flags |= O_FSYNC; error = git_futils_writebuffer(&buf, git_buf_cstr(&path), open_flags, GIT_REFLOG_FILE_MODE); diff --git a/src/settings.c b/src/settings.c index f3120ff57..24e549ec1 100644 --- a/src/settings.c +++ b/src/settings.c @@ -227,8 +227,8 @@ int git_libgit2_opts(int key, ...) git_smart__ofs_delta_enabled = (va_arg(ap, int) != 0); break; - case GIT_OPT_ENABLE_SYNCHRONIZED_OBJECT_CREATION: - git_object__synchronized_writing = (va_arg(ap, int) != 0); + case GIT_OPT_ENABLE_SYNCHRONOUS_OBJECT_CREATION: + git_object__synchronous_writing = (va_arg(ap, int) != 0); break; default: diff --git a/tests/odb/loose.c b/tests/odb/loose.c index 43dabcb0c..fd4a53837 100644 --- a/tests/odb/loose.c +++ b/tests/odb/loose.c @@ -62,7 +62,7 @@ void test_odb_loose__initialize(void) void test_odb_loose__cleanup(void) { - cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SYNCHRONIZED_OBJECT_CREATION, 0)); + cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SYNCHRONOUS_OBJECT_CREATION, 0)); cl_fixture_cleanup("test-objects"); } @@ -180,7 +180,7 @@ void test_odb_loose__fsync_obeys_odb_option(void) void test_odb_loose__fsync_obeys_global_setting(void) { - cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SYNCHRONIZED_OBJECT_CREATION, 1)); + cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SYNCHRONOUS_OBJECT_CREATION, 1)); write_object_to_loose_odb(0); cl_assert(p_fsync__cnt > 0); } diff --git a/tests/pack/packbuilder.c b/tests/pack/packbuilder.c index 77f61f79b..96d643ab7 100644 --- a/tests/pack/packbuilder.c +++ b/tests/pack/packbuilder.c @@ -31,7 +31,7 @@ void test_pack_packbuilder__cleanup(void) git_oid *o; unsigned int i; - cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SYNCHRONIZED_OBJECT_CREATION, 0)); + cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SYNCHRONOUS_OBJECT_CREATION, 0)); if (_commits_is_initialized) { _commits_is_initialized = 0; @@ -200,7 +200,7 @@ void test_pack_packbuilder__does_not_fsync_by_default(void) void test_pack_packbuilder__fsync_when_asked(void) { - cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SYNCHRONIZED_OBJECT_CREATION, 1)); + cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SYNCHRONOUS_OBJECT_CREATION, 1)); p_fsync__cnt = 0; seed_packbuilder(); git_packbuilder_write(_packbuilder, ".", 0666, NULL, NULL); diff --git a/tests/refs/create.c b/tests/refs/create.c index e9630e853..fdbef9f32 100644 --- a/tests/refs/create.c +++ b/tests/refs/create.c @@ -22,7 +22,7 @@ void test_refs_create__cleanup(void) cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_STRICT_OBJECT_CREATION, 1)); cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_STRICT_SYMBOLIC_REF_CREATION, 1)); - cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SYNCHRONIZED_OBJECT_CREATION, 0)); + cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SYNCHRONOUS_OBJECT_CREATION, 0)); } void test_refs_create__symbolic(void) @@ -323,7 +323,7 @@ void test_refs_create__fsyncs_when_requested(void) git_refdb *refdb; git_oid id; - cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SYNCHRONIZED_OBJECT_CREATION, 1)); + cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SYNCHRONOUS_OBJECT_CREATION, 1)); p_fsync__cnt = 0; git_oid_fromstr(&id, current_master_tip); From 3ac05d11493d0573dbf725a19403dbf5e8d93b50 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 17 Feb 2017 16:48:03 +0000 Subject: [PATCH 161/366] win32: don't fsync parent directories on Windows Windows doesn't support it. --- src/fileops.c | 5 +++++ tests/pack/packbuilder.c | 11 ++++++++++- tests/refs/create.c | 15 +++++++++++++-- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/fileops.c b/src/fileops.c index 881d1bed4..6565eb4bd 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -1127,6 +1127,10 @@ void git_futils_filestamp_set_from_stat( int git_futils_fsync_dir(const char *path) { +#ifdef GIT_WIN32 + GIT_UNUSED(path); + return 0; +#else int fd, error = -1; if ((fd = p_open(path, O_RDONLY)) < 0) { @@ -1139,6 +1143,7 @@ int git_futils_fsync_dir(const char *path) p_close(fd); return error; +#endif } int git_futils_fsync_parent(const char *path) diff --git a/tests/pack/packbuilder.c b/tests/pack/packbuilder.c index 96d643ab7..5cdd9a8d2 100644 --- a/tests/pack/packbuilder.c +++ b/tests/pack/packbuilder.c @@ -200,11 +200,20 @@ void test_pack_packbuilder__does_not_fsync_by_default(void) void test_pack_packbuilder__fsync_when_asked(void) { + /* We fsync the packfile and index. On non-Windows, we also fsync + * the parent directories. + */ +#ifdef GIT_WIN32 + int expected = 2; +#else + int expected = 4; +#endif + cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SYNCHRONOUS_OBJECT_CREATION, 1)); p_fsync__cnt = 0; seed_packbuilder(); git_packbuilder_write(_packbuilder, ".", 0666, NULL, NULL); - cl_assert_equal_sz(4, p_fsync__cnt); + cl_assert_equal_sz(expected, p_fsync__cnt); } static int foreach_cb(void *buf, size_t len, void *payload) diff --git a/tests/refs/create.c b/tests/refs/create.c index fdbef9f32..6265aee47 100644 --- a/tests/refs/create.c +++ b/tests/refs/create.c @@ -323,13 +323,24 @@ void test_refs_create__fsyncs_when_requested(void) git_refdb *refdb; git_oid id; + /* Creating a loose ref involves fsync'ing the reference, the + * reflog and (on non-Windows) the containing directories. + * Creating a packed ref involves fsync'ing the packed ref file + * and (on non-Windows) the containing directory. + */ +#ifdef GIT_WIN32 + int expected_create = 2, expected_compress = 1; +#else + int expected_create = 4, expected_compress = 2; +#endif + cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SYNCHRONOUS_OBJECT_CREATION, 1)); p_fsync__cnt = 0; git_oid_fromstr(&id, current_master_tip); cl_git_pass(git_reference_create(&ref, g_repo, "refs/heads/fsync_test", &id, 0, "log message")); git_reference_free(ref); - cl_assert_equal_i(4, p_fsync__cnt); + cl_assert_equal_i(expected_create, p_fsync__cnt); p_fsync__cnt = 0; @@ -337,5 +348,5 @@ void test_refs_create__fsyncs_when_requested(void) cl_git_pass(git_refdb_compress(refdb)); git_refdb_free(refdb); - cl_assert_equal_i(2, p_fsync__cnt); + cl_assert_equal_i(expected_compress, p_fsync__cnt); } From 397cf1a1f5354b856e44f4d890868aad4d76240c Mon Sep 17 00:00:00 2001 From: Richard Ipsum Date: Tue, 28 Feb 2017 22:22:02 +0000 Subject: [PATCH 162/366] Add test for inclusion of (merge) in reflog This test ensures that the string '(merge)' is included in the reflog when a merge commit is made. --- tests/refs/reflog/reflog.c | 44 +++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/tests/refs/reflog/reflog.c b/tests/refs/reflog/reflog.c index 9e46c8ae9..252242152 100644 --- a/tests/refs/reflog/reflog.c +++ b/tests/refs/reflog/reflog.c @@ -4,7 +4,7 @@ #include "git2/reflog.h" #include "reflog.h" - +static const char *merge_reflog_message = "commit (merge): Merge commit"; static const char *new_ref = "refs/heads/test-reflog"; static const char *current_master_tip = "a65fedf39aefe402d3bb6e24df4d4f5fe4547750"; #define commit_msg "commit: bla bla" @@ -448,3 +448,45 @@ void test_refs_reflog_reflog__logallrefupdates_nonbare_set_false(void) assert_no_reflog_update(); } + +void test_refs_reflog_reflog__show_merge_for_merge_commits(void) +{ + git_oid b1_oid; + git_oid b2_oid; + git_oid merge_commit_oid; + git_commit *b1_commit; + git_commit *b2_commit; + git_signature *s; + git_commit *parent_commits[2]; + git_tree *tree; + git_reflog *log; + const git_reflog_entry *entry; + + cl_git_pass(git_signature_now(&s, "alice", "alice@example.com")); + + cl_git_pass(git_reference_name_to_id(&b1_oid, g_repo, "HEAD")); + cl_git_pass(git_reference_name_to_id(&b2_oid, g_repo, "refs/heads/test")); + + cl_git_pass(git_commit_lookup(&b1_commit, g_repo, &b1_oid)); + cl_git_pass(git_commit_lookup(&b2_commit, g_repo, &b2_oid)); + + parent_commits[0] = b1_commit; + parent_commits[1] = b2_commit; + + cl_git_pass(git_commit_tree(&tree, b1_commit)); + + cl_git_pass(git_commit_create(&merge_commit_oid, + g_repo, "HEAD", s, s, NULL, + "Merge commit", tree, + 2, (const struct git_commit **) parent_commits)); + + cl_git_pass(git_reflog_read(&log, g_repo, "HEAD")); + entry = git_reflog_entry_byindex(log, 0); + cl_assert_equal_s(merge_reflog_message, git_reflog_entry_message(entry)); + + git_reflog_free(log); + git_tree_free(tree); + git_commit_free(b1_commit); + git_commit_free(b2_commit); + git_signature_free(s); +} From 5aa1f12a81350b72f57f2050edb0dd60efff5ef1 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 1 Mar 2017 07:45:14 +0100 Subject: [PATCH 163/366] tests: refs::create: fix memory leak --- tests/refs/create.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/refs/create.c b/tests/refs/create.c index db6f8878d..aca808c8c 100644 --- a/tests/refs/create.c +++ b/tests/refs/create.c @@ -92,6 +92,7 @@ void test_refs_create__symbolic_with_arbitrary_content(void) cl_assert(git_reference_type(looked_up_ref) & GIT_REF_SYMBOLIC); cl_assert(reference_is_packed(looked_up_ref) == 0); cl_assert_equal_s(looked_up_ref->name, new_head_tracker); + git_reference_free(looked_up_ref); /* Ensure the target is what we expect it to be */ cl_assert_equal_s(git_reference_symbolic_target(new_reference), arbitrary_target); @@ -111,7 +112,6 @@ void test_refs_create__symbolic_with_arbitrary_content(void) git_repository_free(repo2); git_reference_free(new_reference); git_reference_free(looked_up_ref); - } void test_refs_create__deep_symbolic(void) From b65a5e9ba90e53b6299c49568198e617886ef122 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 1 Mar 2017 07:58:40 +0100 Subject: [PATCH 164/366] winhttp: disambiguate error messages when sending requests --- src/transports/winhttp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c index ae41725a7..e8e848026 100644 --- a/src/transports/winhttp.c +++ b/src/transports/winhttp.c @@ -881,7 +881,7 @@ static int send_request(winhttp_stream *s, size_t len, int ignore_length) } if ((error = do_send_request(s, len, ignore_length)) < 0) - giterr_set(GITERR_OS, "failed to send request"); + giterr_set(GITERR_OS, "failed to send request with unchecked certificate"); return error; } From a02e8a388258d86c898d680e38897575f8de17ef Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 1 Mar 2017 13:58:15 +0100 Subject: [PATCH 165/366] cmake: only enable supported compiler warning flags We currently unconditionally enable the "-Wall" and "-Wextra" flags. Some platforms rely on compilers which do not support these flags, though. One of these platforms is Haiku, which does not support "-Wextra" due to being stuck on GCC version 2. Fix builds on such platforms by adding these flags only if supported by the compiler. --- CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4bfd1b499..317ad34f9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -464,7 +464,10 @@ IF (MSVC) # Precompiled headers ELSE () - SET(CMAKE_C_FLAGS "-D_GNU_SOURCE -Wall -Wextra ${CMAKE_C_FLAGS}") + SET(CMAKE_C_FLAGS "-D_GNU_SOURCE ${CMAKE_C_FLAGS}") + + ADD_C_FLAG_IF_SUPPORTED(-Wall) + ADD_C_FLAG_IF_SUPPORTED(-Wextra) IF (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)") SET(CMAKE_C_FLAGS "-std=c99 -D_POSIX_C_SOURCE=200112L -D__EXTENSIONS__ -D_POSIX_PTHREAD_SEMANTICS ${CMAKE_C_FLAGS}") From 1c04a96b25da048221f31ecee0227d960dc00489 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Tue, 28 Feb 2017 12:29:29 +0000 Subject: [PATCH 166/366] Honor `core.fsyncObjectFiles` --- src/config_cache.c | 1 + src/indexer.c | 17 +++++++-- src/indexer.h | 12 ++++++ src/odb.c | 28 +++++++++++--- src/odb.h | 17 +++++++++ src/pack-objects.c | 4 ++ src/pack-objects.h | 1 + src/refdb_fs.c | 10 +++-- src/repository.c | 22 ++++++----- src/repository.h | 3 ++ tests/odb/loose.c | 21 +++++++++++ tests/pack/packbuilder.c | 25 +++++++++---- tests/refs/create.c | 81 ++++++++++++++++++++++++---------------- 13 files changed, 180 insertions(+), 62 deletions(-) create mode 100644 src/indexer.h diff --git a/src/config_cache.c b/src/config_cache.c index dbea871b9..840722274 100644 --- a/src/config_cache.c +++ b/src/config_cache.c @@ -78,6 +78,7 @@ static struct map_data _cvar_maps[] = { {"core.logallrefupdates", NULL, 0, GIT_LOGALLREFUPDATES_DEFAULT }, {"core.protecthfs", NULL, 0, GIT_PROTECTHFS_DEFAULT }, {"core.protectntfs", NULL, 0, GIT_PROTECTNTFS_DEFAULT }, + {"core.fsyncobjectfiles", NULL, 0, GIT_FSYNCOBJECTFILES_DEFAULT }, }; int git_config__cvar(int *out, git_config *config, git_cvar_cached cvar) diff --git a/src/indexer.c b/src/indexer.c index 3fd7223e5..ce67240ce 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -34,7 +34,8 @@ struct git_indexer { unsigned int parsed_header :1, pack_committed :1, have_stream :1, - have_delta :1; + have_delta :1, + do_fsync :1; struct git_pack_header hdr; struct git_pack_file *pack; unsigned int mode; @@ -124,6 +125,9 @@ int git_indexer_new( git_hash_ctx_init(&idx->hash_ctx); git_hash_ctx_init(&idx->trailer); + if (git_object__synchronous_writing) + idx->do_fsync = 1; + error = git_buf_joinpath(&path, prefix, suff); if (error < 0) goto cleanup; @@ -162,6 +166,11 @@ cleanup: return -1; } +void git_indexer__set_fsync(git_indexer *idx, int do_fsync) +{ + idx->do_fsync = !!do_fsync; +} + /* Try to store the delta so we can try to resolve it later */ static int store_delta(git_indexer *idx) { @@ -991,7 +1000,7 @@ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats) if (git_filebuf_open(&index_file, filename.ptr, GIT_FILEBUF_HASH_CONTENTS | - (git_object__synchronous_writing ? GIT_FILEBUF_FSYNC : 0), + (idx->do_fsync ? GIT_FILEBUF_FSYNC : 0), idx->mode) < 0) goto on_error; @@ -1069,7 +1078,7 @@ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats) return -1; } - if (git_object__synchronous_writing && p_fsync(idx->pack->mwf.fd) < 0) { + if (idx->do_fsync && p_fsync(idx->pack->mwf.fd) < 0) { giterr_set(GITERR_OS, "failed to fsync packfile"); goto on_error; } @@ -1090,7 +1099,7 @@ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats) goto on_error; /* And fsync the parent directory if we're asked to. */ - if (git_object__synchronous_writing && + if (idx->do_fsync && git_futils_fsync_parent(git_buf_cstr(&filename)) < 0) goto on_error; diff --git a/src/indexer.h b/src/indexer.h new file mode 100644 index 000000000..702694bbf --- /dev/null +++ b/src/indexer.h @@ -0,0 +1,12 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ +#ifndef INCLUDE_indexer_h__ +#define INCLUDE_indexer_h__ + +extern int git_indexer__set_fsync(git_indexer *idx, int do_fsync); + +#endif diff --git a/src/odb.c b/src/odb.c index dc98a6ff7..0e0dc5256 100644 --- a/src/odb.c +++ b/src/odb.c @@ -496,7 +496,7 @@ int git_odb_get_backend(git_odb_backend **out, git_odb *odb, size_t pos) return GIT_ENOTFOUND; } -static int add_default_backends( +int git_odb__add_default_backends( git_odb *db, const char *objects_dir, bool as_alternates, int alternate_depth) { @@ -531,7 +531,7 @@ static int add_default_backends( #endif /* add the loose object backend */ - if (git_odb_backend_loose(&loose, objects_dir, -1, 0, 0, 0) < 0 || + if (git_odb_backend_loose(&loose, objects_dir, -1, db->do_fsync, 0, 0) < 0 || add_backend_internal(db, loose, GIT_LOOSE_PRIORITY, as_alternates, inode) < 0) return -1; @@ -586,7 +586,7 @@ static int load_alternates(git_odb *odb, const char *objects_dir, int alternate_ alternate = git_buf_cstr(&alternates_path); } - if ((result = add_default_backends(odb, alternate, true, alternate_depth + 1)) < 0) + if ((result = git_odb__add_default_backends(odb, alternate, true, alternate_depth + 1)) < 0) break; } @@ -598,7 +598,7 @@ static int load_alternates(git_odb *odb, const char *objects_dir, int alternate_ int git_odb_add_disk_alternate(git_odb *odb, const char *path) { - return add_default_backends(odb, path, true, 0); + return git_odb__add_default_backends(odb, path, true, 0); } int git_odb_open(git_odb **out, const char *objects_dir) @@ -612,7 +612,7 @@ int git_odb_open(git_odb **out, const char *objects_dir) if (git_odb_new(&db) < 0) return -1; - if (add_default_backends(db, objects_dir, 0, 0) < 0) { + if (git_odb__add_default_backends(db, objects_dir, 0, 0) < 0) { git_odb_free(db); return -1; } @@ -621,6 +621,24 @@ int git_odb_open(git_odb **out, const char *objects_dir) return 0; } +int git_odb__set_caps(git_odb *odb, int caps) +{ + if (caps == GIT_ODB_CAP_FROM_OWNER) { + git_repository *repo = odb->rc.owner; + int val; + + if (!repo) { + giterr_set(GITERR_ODB, "cannot access repository to set odb caps"); + return -1; + } + + if (!git_repository__cvar(&val, repo, GIT_CVAR_FSYNCOBJECTFILES)) + odb->do_fsync = !!val; + } + + return 0; +} + static void odb_free(git_odb *db) { size_t i; diff --git a/src/odb.h b/src/odb.h index 31a9fd1b9..8ae0643ae 100644 --- a/src/odb.h +++ b/src/odb.h @@ -38,8 +38,25 @@ struct git_odb { git_refcount rc; git_vector backends; git_cache own_cache; + unsigned int do_fsync :1; }; +typedef enum { + GIT_ODB_CAP_FROM_OWNER = -1, +} git_odb_cap_t; + +/* + * Set the capabilities for the object database. + */ +int git_odb__set_caps(git_odb *odb, int caps); + +/* + * Add the default loose and packed backends for a database. + */ +int git_odb__add_default_backends( + git_odb *db, const char *objects_dir, + bool as_alternates, int alternate_depth); + /* * Hash a git_rawobj internally. * The `git_rawobj` is supposed to be previously initialized diff --git a/src/pack-objects.c b/src/pack-objects.c index 58b7b94b3..ef272e8f5 100644 --- a/src/pack-objects.c +++ b/src/pack-objects.c @@ -1385,6 +1385,7 @@ int git_packbuilder_write( git_indexer *indexer; git_transfer_progress stats; struct pack_write_context ctx; + int t; PREPARE_PACK; @@ -1392,6 +1393,9 @@ int git_packbuilder_write( &indexer, path, mode, pb->odb, progress_cb, progress_cb_payload) < 0) return -1; + if (!git_repository__cvar(&t, pb->repo, GIT_CVAR_FSYNCOBJECTFILES) && t) + git_indexer__set_fsync(indexer, 1); + ctx.indexer = indexer; ctx.stats = &stats; diff --git a/src/pack-objects.h b/src/pack-objects.h index 5a84f4158..e1e0ee3c8 100644 --- a/src/pack-objects.h +++ b/src/pack-objects.h @@ -16,6 +16,7 @@ #include "netops.h" #include "zstream.h" #include "pool.h" +#include "indexer.h" #include "git2/oid.h" #include "git2/pack.h" diff --git a/src/refdb_fs.c b/src/refdb_fs.c index d7a458a87..ade50f7c3 100644 --- a/src/refdb_fs.c +++ b/src/refdb_fs.c @@ -62,6 +62,7 @@ typedef struct refdb_fs_backend { int peeling_mode; git_iterator_flag_t iterator_flags; uint32_t direach_flags; + int fsync; } refdb_fs_backend; static int refdb_reflog_fs__delete(git_refdb_backend *_backend, const char *name); @@ -756,7 +757,7 @@ static int loose_lock(git_filebuf *file, refdb_fs_backend *backend, const char * return -1; filebuf_flags = GIT_FILEBUF_FORCE; - if (git_object__synchronous_writing) + if (backend->fsync) filebuf_flags |= GIT_FILEBUF_FSYNC; error = git_filebuf_open(file, ref_path.ptr, filebuf_flags, GIT_REFS_FILE_MODE); @@ -1001,7 +1002,7 @@ static int packed_write(refdb_fs_backend *backend) if ((error = git_sortedcache_wlock(refcache)) < 0) return error; - if (git_object__synchronous_writing) + if (backend->fsync) open_flags = GIT_FILEBUF_FSYNC; /* Open the file! */ @@ -1861,7 +1862,7 @@ static int reflog_append(refdb_fs_backend *backend, const git_reference *ref, co open_flags = O_WRONLY | O_CREAT | O_APPEND; - if (git_object__synchronous_writing) + if (backend->fsync) open_flags |= O_FSYNC; error = git_futils_writebuffer(&buf, git_buf_cstr(&path), open_flags, GIT_REFLOG_FILE_MODE); @@ -2014,6 +2015,9 @@ int git_refdb_backend_fs( backend->iterator_flags |= GIT_ITERATOR_PRECOMPOSE_UNICODE; backend->direach_flags |= GIT_PATH_DIR_PRECOMPOSE_UNICODE; } + if ((!git_repository__cvar(&t, backend->repo, GIT_CVAR_FSYNCOBJECTFILES) && t) || + git_object__synchronous_writing) + backend->fsync = 1; backend->parent.exists = &refdb_fs_backend__exists; backend->parent.lookup = &refdb_fs_backend__lookup; diff --git a/src/repository.c b/src/repository.c index 0db481638..425ef796f 100644 --- a/src/repository.c +++ b/src/repository.c @@ -1055,18 +1055,22 @@ int git_repository_odb__weakptr(git_odb **out, git_repository *repo) git_odb *odb; if ((error = git_repository_item_path(&odb_path, repo, - GIT_REPOSITORY_ITEM_OBJECTS)) < 0) + GIT_REPOSITORY_ITEM_OBJECTS)) < 0 || + (error = git_odb_new(&odb)) < 0) return error; - error = git_odb_open(&odb, odb_path.ptr); - if (!error) { - GIT_REFCOUNT_OWN(odb, repo); + GIT_REFCOUNT_OWN(odb, repo); - odb = git__compare_and_swap(&repo->_odb, NULL, odb); - if (odb != NULL) { - GIT_REFCOUNT_OWN(odb, NULL); - git_odb_free(odb); - } + if ((error = git_odb__set_caps(odb, GIT_ODB_CAP_FROM_OWNER)) < 0 || + (error = git_odb__add_default_backends(odb, odb_path.ptr, 0, 0)) < 0) { + git_odb_free(odb); + return error; + } + + odb = git__compare_and_swap(&repo->_odb, NULL, odb); + if (odb != NULL) { + GIT_REFCOUNT_OWN(odb, NULL); + git_odb_free(odb); } git_buf_free(&odb_path); diff --git a/src/repository.h b/src/repository.h index c328ecd21..33adfa60a 100644 --- a/src/repository.h +++ b/src/repository.h @@ -46,6 +46,7 @@ typedef enum { GIT_CVAR_LOGALLREFUPDATES, /* core.logallrefupdates */ GIT_CVAR_PROTECTHFS, /* core.protectHFS */ GIT_CVAR_PROTECTNTFS, /* core.protectNTFS */ + GIT_CVAR_FSYNCOBJECTFILES, /* core.fsyncObjectFiles */ GIT_CVAR_CACHE_MAX } git_cvar_cached; @@ -106,6 +107,8 @@ typedef enum { GIT_PROTECTHFS_DEFAULT = GIT_CVAR_FALSE, /* core.protectNTFS */ GIT_PROTECTNTFS_DEFAULT = GIT_CVAR_FALSE, + /* core.fsyncObjectFiles */ + GIT_FSYNCOBJECTFILES_DEFAULT = GIT_CVAR_FALSE, } git_cvar_value; /* internal repository init flags */ diff --git a/tests/odb/loose.c b/tests/odb/loose.c index fd4a53837..dd686aa01 100644 --- a/tests/odb/loose.c +++ b/tests/odb/loose.c @@ -3,6 +3,7 @@ #include "git2/odb_backend.h" #include "posix.h" #include "loose_data.h" +#include "repository.h" #ifdef __ANDROID_API__ # define S_IREAD S_IRUSR @@ -184,3 +185,23 @@ void test_odb_loose__fsync_obeys_global_setting(void) write_object_to_loose_odb(0); cl_assert(p_fsync__cnt > 0); } + +void test_odb_loose__fsync_obeys_repo_setting(void) +{ + git_repository *repo; + git_odb *odb; + git_oid oid; + + cl_git_pass(git_repository_init(&repo, "test-objects", 1)); + cl_git_pass(git_repository_odb__weakptr(&odb, repo)); + cl_git_pass(git_odb_write(&oid, odb, "No fsync here\n", 14, GIT_OBJ_BLOB)); + cl_assert(p_fsync__cnt == 0); + git_repository_free(repo); + + cl_git_pass(git_repository_open(&repo, "test-objects")); + cl_repo_set_bool(repo, "core.fsyncObjectFiles", true); + cl_git_pass(git_repository_odb__weakptr(&odb, repo)); + cl_git_pass(git_odb_write(&oid, odb, "Now fsync\n", 10, GIT_OBJ_BLOB)); + cl_assert(p_fsync__cnt > 0); + git_repository_free(repo); +} diff --git a/tests/pack/packbuilder.c b/tests/pack/packbuilder.c index 5cdd9a8d2..1d7becef7 100644 --- a/tests/pack/packbuilder.c +++ b/tests/pack/packbuilder.c @@ -198,22 +198,31 @@ void test_pack_packbuilder__does_not_fsync_by_default(void) cl_assert_equal_sz(0, p_fsync__cnt); } -void test_pack_packbuilder__fsync_when_asked(void) -{ - /* We fsync the packfile and index. On non-Windows, we also fsync - * the parent directories. - */ +/* We fsync the packfile and index. On non-Windows, we also fsync + * the parent directories. + */ #ifdef GIT_WIN32 - int expected = 2; +static int expected_fsyncs = 2; #else - int expected = 4; +static int expected_fsyncs = 4; #endif +void test_pack_packbuilder__fsync_global_setting(void) +{ cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SYNCHRONOUS_OBJECT_CREATION, 1)); p_fsync__cnt = 0; seed_packbuilder(); git_packbuilder_write(_packbuilder, ".", 0666, NULL, NULL); - cl_assert_equal_sz(expected, p_fsync__cnt); + cl_assert_equal_sz(expected_fsyncs, p_fsync__cnt); +} + +void test_pack_packbuilder__fsync_repo_setting(void) +{ + cl_repo_set_bool(_repo, "core.fsyncObjectFiles", true); + p_fsync__cnt = 0; + seed_packbuilder(); + git_packbuilder_write(_packbuilder, ".", 0666, NULL, NULL); + cl_assert_equal_sz(expected_fsyncs, p_fsync__cnt); } static int foreach_cb(void *buf, size_t len, void *payload) diff --git a/tests/refs/create.c b/tests/refs/create.c index 6265aee47..7b582d708 100644 --- a/tests/refs/create.c +++ b/tests/refs/create.c @@ -300,53 +300,68 @@ void test_refs_create__creating_a_loose_ref_with_invalid_windows_name(void) test_win32_name("refs/heads/com1"); } -void test_refs_create__does_not_fsync_by_default(void) -{ - git_reference *ref = NULL; - git_refdb *refdb; - git_oid id; - - git_oid_fromstr(&id, current_master_tip); - cl_git_pass(git_reference_create(&ref, g_repo, "refs/heads/fsync_test", &id, 0, "log message")); - git_reference_free(ref); - - cl_git_pass(git_repository_refdb(&refdb, g_repo)); - cl_git_pass(git_refdb_compress(refdb)); - git_refdb_free(refdb); - - cl_assert_equal_i(0, p_fsync__cnt); -} - -void test_refs_create__fsyncs_when_requested(void) -{ - git_reference *ref = NULL; - git_refdb *refdb; - git_oid id; - - /* Creating a loose ref involves fsync'ing the reference, the - * reflog and (on non-Windows) the containing directories. - * Creating a packed ref involves fsync'ing the packed ref file - * and (on non-Windows) the containing directory. - */ +/* Creating a loose ref involves fsync'ing the reference, the + * reflog and (on non-Windows) the containing directories. + * Creating a packed ref involves fsync'ing the packed ref file + * and (on non-Windows) the containing directory. + */ #ifdef GIT_WIN32 - int expected_create = 2, expected_compress = 1; +static int expected_fsyncs_create = 2, expected_fsyncs_compress = 1; #else - int expected_create = 4, expected_compress = 2; +static int expected_fsyncs_create = 4, expected_fsyncs_compress = 2; #endif - cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SYNCHRONOUS_OBJECT_CREATION, 1)); +static void count_fsyncs(size_t *create_count, size_t *compress_count) +{ + git_reference *ref = NULL; + git_refdb *refdb; + git_oid id; + p_fsync__cnt = 0; git_oid_fromstr(&id, current_master_tip); cl_git_pass(git_reference_create(&ref, g_repo, "refs/heads/fsync_test", &id, 0, "log message")); git_reference_free(ref); - cl_assert_equal_i(expected_create, p_fsync__cnt); + *create_count = p_fsync__cnt; p_fsync__cnt = 0; cl_git_pass(git_repository_refdb(&refdb, g_repo)); cl_git_pass(git_refdb_compress(refdb)); git_refdb_free(refdb); - cl_assert_equal_i(expected_compress, p_fsync__cnt); + *compress_count = p_fsync__cnt; + p_fsync__cnt = 0; +} + +void test_refs_create__does_not_fsync_by_default(void) +{ + size_t create_count, compress_count; + count_fsyncs(&create_count, &compress_count); + + cl_assert_equal_i(0, create_count); + cl_assert_equal_i(0, compress_count); +} + +void test_refs_create__fsyncs_when_global_opt_set(void) +{ + size_t create_count, compress_count; + + cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SYNCHRONOUS_OBJECT_CREATION, 1)); + count_fsyncs(&create_count, &compress_count); + + cl_assert_equal_i(expected_fsyncs_create, create_count); + cl_assert_equal_i(expected_fsyncs_compress, compress_count); +} + +void test_refs_create__fsyncs_when_repo_config_set(void) +{ + size_t create_count, compress_count; + + cl_repo_set_bool(g_repo, "core.fsyncObjectFiles", true); + + count_fsyncs(&create_count, &compress_count); + + cl_assert_equal_i(expected_fsyncs_create, create_count); + cl_assert_equal_i(expected_fsyncs_compress, compress_count); } From a371a8ae94ff234acdc19cb35dead4312465ffce Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 24 Feb 2017 13:03:15 +0000 Subject: [PATCH 167/366] hash: rename implementation selection constants --- CMakeLists.txt | 6 +++--- src/hash.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 317ad34f9..3cf271c63 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -293,12 +293,12 @@ ENDIF() # Specify sha1 implementation IF (WIN32 AND NOT MINGW AND NOT SHA1_TYPE STREQUAL "builtin") - ADD_DEFINITIONS(-DWIN32_SHA1) + ADD_DEFINITIONS(-DGIT_SHA1_WIN32) FILE(GLOB SRC_SHA1 src/hash/hash_win32.c) ELSEIF (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - ADD_DEFINITIONS(-DGIT_COMMON_CRYPTO) + ADD_DEFINITIONS(-DGIT_SHA1_COMMON_CRYPTO) ELSEIF (OPENSSL_FOUND AND NOT SHA1_TYPE STREQUAL "builtin") - ADD_DEFINITIONS(-DOPENSSL_SHA1) + ADD_DEFINITIONS(-DGIT_SHA1_OPENSSL) IF (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") LIST(APPEND LIBGIT2_PC_LIBS "-lssl") ELSE() diff --git a/src/hash.h b/src/hash.h index 0bc02a8a9..76788b18d 100644 --- a/src/hash.h +++ b/src/hash.h @@ -16,11 +16,11 @@ int git_hash_global_init(void); int git_hash_ctx_init(git_hash_ctx *ctx); void git_hash_ctx_cleanup(git_hash_ctx *ctx); -#if defined(GIT_COMMON_CRYPTO) +#if defined(GIT_SHA1_COMMON_CRYPTO) # include "hash/hash_common_crypto.h" -#elif defined(OPENSSL_SHA1) +#elif defined(GIT_SHA1_OPENSSL) # include "hash/hash_openssl.h" -#elif defined(WIN32_SHA1) +#elif defined(GIT_SHA1_WIN32) # include "hash/hash_win32.h" #else # include "hash/hash_generic.h" From 2dfd1294f7a694bfa9e864a9489ae3cb318a5ed0 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 24 Feb 2017 13:34:01 +0000 Subject: [PATCH 168/366] hash: include sha1collisiondetection Include the SHA1 collision attack detection library from https://github.com/cr-marcstevens/sha1collisiondetection --- CMakeLists.txt | 6 +- COPYING | 33 + include/git2/errors.h | 3 +- src/hash.h | 4 +- src/hash/hash_collisiondetect.h | 57 ++ src/hash/sha1dc/sha1.c | 1149 +++++++++++++++++++++++++++++++ src/hash/sha1dc/sha1.h | 94 +++ src/hash/sha1dc/ubc_check.c | 361 ++++++++++ src/hash/sha1dc/ubc_check.h | 35 + 9 files changed, 1739 insertions(+), 3 deletions(-) create mode 100644 src/hash/hash_collisiondetect.h create mode 100644 src/hash/sha1dc/sha1.c create mode 100644 src/hash/sha1dc/sha1.h create mode 100644 src/hash/sha1dc/ubc_check.c create mode 100644 src/hash/sha1dc/ubc_check.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 3cf271c63..dfbf29749 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,6 +37,7 @@ OPTION( PROFILE "Generate profiling information" OFF ) OPTION( ENABLE_TRACE "Enables tracing support" OFF ) OPTION( LIBGIT2_FILENAME "Name of the produced binary" OFF ) +OPTION( USE_SHA1DC "Use SHA-1 with collision detection" OFF ) OPTION( USE_ICONV "Link with and use iconv library" OFF ) OPTION( USE_SSH "Link with libssh to enable SSH support" ON ) OPTION( USE_GSSAPI "Link with libgssapi for SPNEGO auth" OFF ) @@ -292,7 +293,10 @@ ELSE () ENDIF() # Specify sha1 implementation -IF (WIN32 AND NOT MINGW AND NOT SHA1_TYPE STREQUAL "builtin") +IF (USE_SHA1DC) + ADD_DEFINITIONS(-DGIT_SHA1_COLLISIONDETECT) + FILE(GLOB SRC_SHA1 src/hash/hash_collisiondetect.c src/hash/sha1dc/*) +ELSEIF (WIN32 AND NOT MINGW AND NOT SHA1_TYPE STREQUAL "builtin") ADD_DEFINITIONS(-DGIT_SHA1_WIN32) FILE(GLOB SRC_SHA1 src/hash/hash_win32.c) ELSEIF (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") diff --git a/COPYING b/COPYING index 1b88b9b8e..da695ebdb 100644 --- a/COPYING +++ b/COPYING @@ -958,3 +958,36 @@ necessary. Here is a sample; alter the names: That's all there is to it! ---------------------------------------------------------------------- + +The bundled SHA1 collision detection code is licensed under the MIT license: + +MIT License + +Copyright (c) 2017: + Marc Stevens + Cryptology Group + Centrum Wiskunde & Informatica + P.O. Box 94079, 1090 GB Amsterdam, Netherlands + marc@marc-stevens.nl + + Dan Shumow + Microsoft Research + danshu@microsoft.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/include/git2/errors.h b/include/git2/errors.h index 1d271366f..3b746b758 100644 --- a/include/git2/errors.h +++ b/include/git2/errors.h @@ -100,7 +100,8 @@ typedef enum { GITERR_REBASE, GITERR_FILESYSTEM, GITERR_PATCH, - GITERR_WORKTREE + GITERR_WORKTREE, + GITERR_SHA1 } git_error_t; /** diff --git a/src/hash.h b/src/hash.h index 76788b18d..0db0339dc 100644 --- a/src/hash.h +++ b/src/hash.h @@ -16,7 +16,9 @@ int git_hash_global_init(void); int git_hash_ctx_init(git_hash_ctx *ctx); void git_hash_ctx_cleanup(git_hash_ctx *ctx); -#if defined(GIT_SHA1_COMMON_CRYPTO) +#if defined(GIT_SHA1_COLLISIONDETECT) +# include "hash/hash_collisiondetect.h" +#elif defined(GIT_SHA1_COMMON_CRYPTO) # include "hash/hash_common_crypto.h" #elif defined(GIT_SHA1_OPENSSL) # include "hash/hash_openssl.h" diff --git a/src/hash/hash_collisiondetect.h b/src/hash/hash_collisiondetect.h new file mode 100644 index 000000000..2bb27ba14 --- /dev/null +++ b/src/hash/hash_collisiondetect.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#ifndef INCLUDE_hash_collisiondetect_h__ +#define INCLUDE_hash_collisiondetect_h__ + +#include "hash.h" +#include "sha1dc/sha1.h" + +struct git_hash_ctx { + SHA1_CTX c; +}; + +#define git_hash_global_init() 0 +#define git_hash_ctx_init(ctx) git_hash_init(ctx) +#define git_hash_ctx_cleanup(ctx) + +GIT_INLINE(int) git_hash_init(git_hash_ctx *ctx) +{ + assert(ctx); + SHA1DCInit(&ctx->c); + return 0; +} + +GIT_INLINE(int) git_hash_update(git_hash_ctx *ctx, const void *data, size_t len) +{ + const char *p = data; + + assert(ctx); + + /* We expect a size_t, but sha1dc only takes an int */ + while (len > INT_MAX) { + SHA1DCUpdate(&ctx->c, p, INT_MAX); + p += INT_MAX; + len -= INT_MAX; + } + + SHA1DCUpdate(&ctx->c, p, len); + return 0; +} + +GIT_INLINE(int) git_hash_final(git_oid *out, git_hash_ctx *ctx) +{ + assert(ctx); + if (SHA1DCFinal(out->id, &ctx->c)) { + giterr_set(GITERR_SHA1, "SHA1 collision attack detected"); + return -1; + } + + return 0; +} + +#endif /* INCLUDE_hash_collisiondetect_h__ */ diff --git a/src/hash/sha1dc/sha1.c b/src/hash/sha1dc/sha1.c new file mode 100644 index 000000000..c846a163e --- /dev/null +++ b/src/hash/sha1dc/sha1.c @@ -0,0 +1,1149 @@ +/*** +* Copyright 2017 Marc Stevens , Dan Shumow (danshu@microsoft.com) +* Distributed under the MIT Software License. +* See accompanying file LICENSE.txt or copy at +* https://opensource.org/licenses/MIT +***/ + +#include +#include +#include + +#include "sha1.h" +#include "ubc_check.h" + +#define rotate_right(x,n) (((x)>>(n))|((x)<<(32-(n)))) +#define rotate_left(x,n) (((x)<<(n))|((x)>>(32-(n)))) + +#define sha1_f1(b,c,d) ((d)^((b)&((c)^(d)))) +#define sha1_f2(b,c,d) ((b)^(c)^(d)) +#define sha1_f3(b,c,d) (((b) & ((c)|(d))) | ((c)&(d))) +#define sha1_f4(b,c,d) ((b)^(c)^(d)) + +#define HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, m, t) \ + { e += rotate_left(a, 5) + sha1_f1(b,c,d) + 0x5A827999 + m[t]; b = rotate_left(b, 30); } +#define HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, m, t) \ + { e += rotate_left(a, 5) + sha1_f2(b,c,d) + 0x6ED9EBA1 + m[t]; b = rotate_left(b, 30); } +#define HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, m, t) \ + { e += rotate_left(a, 5) + sha1_f3(b,c,d) + 0x8F1BBCDC + m[t]; b = rotate_left(b, 30); } +#define HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, m, t) \ + { e += rotate_left(a, 5) + sha1_f4(b,c,d) + 0xCA62C1D6 + m[t]; b = rotate_left(b, 30); } + +#define HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(a, b, c, d, e, m, t) \ + { b = rotate_right(b, 30); e -= rotate_left(a, 5) + sha1_f1(b,c,d) + 0x5A827999 + m[t]; } +#define HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(a, b, c, d, e, m, t) \ + { b = rotate_right(b, 30); e -= rotate_left(a, 5) + sha1_f2(b,c,d) + 0x6ED9EBA1 + m[t]; } +#define HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(a, b, c, d, e, m, t) \ + { b = rotate_right(b, 30); e -= rotate_left(a, 5) + sha1_f3(b,c,d) + 0x8F1BBCDC + m[t]; } +#define HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(a, b, c, d, e, m, t) \ + { b = rotate_right(b, 30); e -= rotate_left(a, 5) + sha1_f4(b,c,d) + 0xCA62C1D6 + m[t]; } + +#define SHA1_STORE_STATE(i) states[i][0] = a; states[i][1] = b; states[i][2] = c; states[i][3] = d; states[i][4] = e; + + + +void sha1_message_expansion(uint32_t W[80]) +{ + unsigned i; + + for (i = 16; i < 80; ++i) + W[i] = rotate_left(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1); +} + +void sha1_compression(uint32_t ihv[5], const uint32_t m[16]) +{ + uint32_t a, b, c, d, e, W[80]; + unsigned i; + + memcpy(W, m, 16 * 4); + for (i = 16; i < 80; ++i) + W[i] = rotate_left(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1); + + a = ihv[0], b = ihv[1], c = ihv[2], d = ihv[3], e = ihv[4]; + + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 0); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 1); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 2); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 3); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 4); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 5); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 6); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 7); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 8); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 9); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 10); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 11); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 12); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 13); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 14); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 15); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 16); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 17); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 18); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 19); + + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 20); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 21); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 22); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 23); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 24); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 25); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 26); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 27); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 28); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 29); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 30); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 31); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 32); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 33); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 34); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 35); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 36); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 37); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 38); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 39); + + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 40); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 41); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 42); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 43); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 44); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 45); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 46); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 47); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 48); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 49); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 50); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 51); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 52); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 53); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 54); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 55); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 56); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 57); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 58); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 59); + + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 60); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 61); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 62); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 63); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 64); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 65); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 66); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 67); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 68); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 69); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 70); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 71); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 72); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 73); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 74); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 75); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 76); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 77); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 78); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 79); + + ihv[0] += a; ihv[1] += b; ihv[2] += c; ihv[3] += d; ihv[4] += e; +} + + + +void sha1_compression_W(uint32_t ihv[5], const uint32_t W[80]) +{ + uint32_t a = ihv[0], b = ihv[1], c = ihv[2], d = ihv[3], e = ihv[4]; + + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 0); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 1); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 2); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 3); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 4); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 5); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 6); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 7); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 8); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 9); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 10); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 11); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 12); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 13); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 14); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 15); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 16); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 17); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 18); + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 19); + + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 20); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 21); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 22); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 23); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 24); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 25); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 26); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 27); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 28); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 29); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 30); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 31); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 32); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 33); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 34); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 35); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 36); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 37); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 38); + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 39); + + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 40); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 41); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 42); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 43); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 44); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 45); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 46); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 47); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 48); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 49); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 50); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 51); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 52); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 53); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 54); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 55); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 56); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 57); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 58); + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 59); + + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 60); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 61); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 62); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 63); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 64); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 65); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 66); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 67); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 68); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 69); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 70); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 71); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 72); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 73); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 74); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 75); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 76); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 77); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 78); + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 79); + + ihv[0] += a; ihv[1] += b; ihv[2] += c; ihv[3] += d; ihv[4] += e; +} + + + +void sha1_compression_states(uint32_t ihv[5], const uint32_t W[80], uint32_t states[80][5]) +{ + uint32_t a = ihv[0], b = ihv[1], c = ihv[2], d = ihv[3], e = ihv[4]; + +#ifdef DOSTORESTATE00 + SHA1_STORE_STATE(0) +#endif + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 0); + +#ifdef DOSTORESTATE01 + SHA1_STORE_STATE(1) +#endif + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 1); + +#ifdef DOSTORESTATE02 + SHA1_STORE_STATE(2) +#endif + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 2); + +#ifdef DOSTORESTATE03 + SHA1_STORE_STATE(3) +#endif + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 3); + +#ifdef DOSTORESTATE04 + SHA1_STORE_STATE(4) +#endif + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 4); + +#ifdef DOSTORESTATE05 + SHA1_STORE_STATE(5) +#endif + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 5); + +#ifdef DOSTORESTATE06 + SHA1_STORE_STATE(6) +#endif + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 6); + +#ifdef DOSTORESTATE07 + SHA1_STORE_STATE(7) +#endif + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 7); + +#ifdef DOSTORESTATE08 + SHA1_STORE_STATE(8) +#endif + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 8); + +#ifdef DOSTORESTATE09 + SHA1_STORE_STATE(9) +#endif + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 9); + +#ifdef DOSTORESTATE10 + SHA1_STORE_STATE(10) +#endif + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 10); + +#ifdef DOSTORESTATE11 + SHA1_STORE_STATE(11) +#endif + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 11); + +#ifdef DOSTORESTATE12 + SHA1_STORE_STATE(12) +#endif + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 12); + +#ifdef DOSTORESTATE13 + SHA1_STORE_STATE(13) +#endif + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 13); + +#ifdef DOSTORESTATE14 + SHA1_STORE_STATE(14) +#endif + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 14); + +#ifdef DOSTORESTATE15 + SHA1_STORE_STATE(15) +#endif + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 15); + +#ifdef DOSTORESTATE16 + SHA1_STORE_STATE(16) +#endif + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 16); + +#ifdef DOSTORESTATE17 + SHA1_STORE_STATE(17) +#endif + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 17); + +#ifdef DOSTORESTATE18 + SHA1_STORE_STATE(18) +#endif + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 18); + +#ifdef DOSTORESTATE19 + SHA1_STORE_STATE(19) +#endif + HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 19); + + + +#ifdef DOSTORESTATE20 + SHA1_STORE_STATE(20) +#endif + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 20); + +#ifdef DOSTORESTATE21 + SHA1_STORE_STATE(21) +#endif + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 21); + +#ifdef DOSTORESTATE22 + SHA1_STORE_STATE(22) +#endif + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 22); + +#ifdef DOSTORESTATE23 + SHA1_STORE_STATE(23) +#endif + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 23); + +#ifdef DOSTORESTATE24 + SHA1_STORE_STATE(24) +#endif + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 24); + +#ifdef DOSTORESTATE25 + SHA1_STORE_STATE(25) +#endif + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 25); + +#ifdef DOSTORESTATE26 + SHA1_STORE_STATE(26) +#endif + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 26); + +#ifdef DOSTORESTATE27 + SHA1_STORE_STATE(27) +#endif + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 27); + +#ifdef DOSTORESTATE28 + SHA1_STORE_STATE(28) +#endif + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 28); + +#ifdef DOSTORESTATE29 + SHA1_STORE_STATE(29) +#endif + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 29); + +#ifdef DOSTORESTATE30 + SHA1_STORE_STATE(30) +#endif + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 30); + +#ifdef DOSTORESTATE31 + SHA1_STORE_STATE(31) +#endif + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 31); + +#ifdef DOSTORESTATE32 + SHA1_STORE_STATE(32) +#endif + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 32); + +#ifdef DOSTORESTATE33 + SHA1_STORE_STATE(33) +#endif + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 33); + +#ifdef DOSTORESTATE34 + SHA1_STORE_STATE(34) +#endif + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 34); + +#ifdef DOSTORESTATE35 + SHA1_STORE_STATE(35) +#endif + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 35); + +#ifdef DOSTORESTATE36 + SHA1_STORE_STATE(36) +#endif + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 36); + +#ifdef DOSTORESTATE37 + SHA1_STORE_STATE(37) +#endif + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 37); + +#ifdef DOSTORESTATE38 + SHA1_STORE_STATE(38) +#endif + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 38); + +#ifdef DOSTORESTATE39 + SHA1_STORE_STATE(39) +#endif + HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 39); + + + +#ifdef DOSTORESTATE40 + SHA1_STORE_STATE(40) +#endif + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 40); + +#ifdef DOSTORESTATE41 + SHA1_STORE_STATE(41) +#endif + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 41); + +#ifdef DOSTORESTATE42 + SHA1_STORE_STATE(42) +#endif + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 42); + +#ifdef DOSTORESTATE43 + SHA1_STORE_STATE(43) +#endif + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 43); + +#ifdef DOSTORESTATE44 + SHA1_STORE_STATE(44) +#endif + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 44); + +#ifdef DOSTORESTATE45 + SHA1_STORE_STATE(45) +#endif + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 45); + +#ifdef DOSTORESTATE46 + SHA1_STORE_STATE(46) +#endif + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 46); + +#ifdef DOSTORESTATE47 + SHA1_STORE_STATE(47) +#endif + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 47); + +#ifdef DOSTORESTATE48 + SHA1_STORE_STATE(48) +#endif + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 48); + +#ifdef DOSTORESTATE49 + SHA1_STORE_STATE(49) +#endif + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 49); + +#ifdef DOSTORESTATE50 + SHA1_STORE_STATE(50) +#endif + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 50); + +#ifdef DOSTORESTATE51 + SHA1_STORE_STATE(51) +#endif + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 51); + +#ifdef DOSTORESTATE52 + SHA1_STORE_STATE(52) +#endif + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 52); + +#ifdef DOSTORESTATE53 + SHA1_STORE_STATE(53) +#endif + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 53); + +#ifdef DOSTORESTATE54 + SHA1_STORE_STATE(54) +#endif + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 54); + +#ifdef DOSTORESTATE55 + SHA1_STORE_STATE(55) +#endif + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 55); + +#ifdef DOSTORESTATE56 + SHA1_STORE_STATE(56) +#endif + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 56); + +#ifdef DOSTORESTATE57 + SHA1_STORE_STATE(57) +#endif + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 57); + +#ifdef DOSTORESTATE58 + SHA1_STORE_STATE(58) +#endif + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 58); + +#ifdef DOSTORESTATE59 + SHA1_STORE_STATE(59) +#endif + HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 59); + + + + +#ifdef DOSTORESTATE60 + SHA1_STORE_STATE(60) +#endif + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 60); + +#ifdef DOSTORESTATE61 + SHA1_STORE_STATE(61) +#endif + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 61); + +#ifdef DOSTORESTATE62 + SHA1_STORE_STATE(62) +#endif + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 62); + +#ifdef DOSTORESTATE63 + SHA1_STORE_STATE(63) +#endif + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 63); + +#ifdef DOSTORESTATE64 + SHA1_STORE_STATE(64) +#endif + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 64); + +#ifdef DOSTORESTATE65 + SHA1_STORE_STATE(65) +#endif + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 65); + +#ifdef DOSTORESTATE66 + SHA1_STORE_STATE(66) +#endif + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 66); + +#ifdef DOSTORESTATE67 + SHA1_STORE_STATE(67) +#endif + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 67); + +#ifdef DOSTORESTATE68 + SHA1_STORE_STATE(68) +#endif + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 68); + +#ifdef DOSTORESTATE69 + SHA1_STORE_STATE(69) +#endif + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 69); + +#ifdef DOSTORESTATE70 + SHA1_STORE_STATE(70) +#endif + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 70); + +#ifdef DOSTORESTATE71 + SHA1_STORE_STATE(71) +#endif + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 71); + +#ifdef DOSTORESTATE72 + SHA1_STORE_STATE(72) +#endif + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 72); + +#ifdef DOSTORESTATE73 + SHA1_STORE_STATE(73) +#endif + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 73); + +#ifdef DOSTORESTATE74 + SHA1_STORE_STATE(74) +#endif + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 74); + +#ifdef DOSTORESTATE75 + SHA1_STORE_STATE(75) +#endif + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 75); + +#ifdef DOSTORESTATE76 + SHA1_STORE_STATE(76) +#endif + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 76); + +#ifdef DOSTORESTATE77 + SHA1_STORE_STATE(77) +#endif + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 77); + +#ifdef DOSTORESTATE78 + SHA1_STORE_STATE(78) +#endif + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 78); + +#ifdef DOSTORESTATE79 + SHA1_STORE_STATE(79) +#endif + HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 79); + + + + ihv[0] += a; ihv[1] += b; ihv[2] += c; ihv[3] += d; ihv[4] += e; +} + + + + +#define SHA1_RECOMPRESS(t) \ +void sha1recompress_fast_ ## t (uint32_t ihvin[5], uint32_t ihvout[5], const uint32_t me2[80], const uint32_t state[5]) \ +{ \ + uint32_t a = state[0], b = state[1], c = state[2], d = state[3], e = state[4]; \ + if (t > 79) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(b, c, d, e, a, me2, 79); \ + if (t > 78) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(c, d, e, a, b, me2, 78); \ + if (t > 77) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(d, e, a, b, c, me2, 77); \ + if (t > 76) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(e, a, b, c, d, me2, 76); \ + if (t > 75) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(a, b, c, d, e, me2, 75); \ + if (t > 74) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(b, c, d, e, a, me2, 74); \ + if (t > 73) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(c, d, e, a, b, me2, 73); \ + if (t > 72) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(d, e, a, b, c, me2, 72); \ + if (t > 71) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(e, a, b, c, d, me2, 71); \ + if (t > 70) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(a, b, c, d, e, me2, 70); \ + if (t > 69) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(b, c, d, e, a, me2, 69); \ + if (t > 68) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(c, d, e, a, b, me2, 68); \ + if (t > 67) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(d, e, a, b, c, me2, 67); \ + if (t > 66) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(e, a, b, c, d, me2, 66); \ + if (t > 65) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(a, b, c, d, e, me2, 65); \ + if (t > 64) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(b, c, d, e, a, me2, 64); \ + if (t > 63) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(c, d, e, a, b, me2, 63); \ + if (t > 62) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(d, e, a, b, c, me2, 62); \ + if (t > 61) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(e, a, b, c, d, me2, 61); \ + if (t > 60) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(a, b, c, d, e, me2, 60); \ + if (t > 59) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(b, c, d, e, a, me2, 59); \ + if (t > 58) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(c, d, e, a, b, me2, 58); \ + if (t > 57) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(d, e, a, b, c, me2, 57); \ + if (t > 56) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(e, a, b, c, d, me2, 56); \ + if (t > 55) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(a, b, c, d, e, me2, 55); \ + if (t > 54) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(b, c, d, e, a, me2, 54); \ + if (t > 53) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(c, d, e, a, b, me2, 53); \ + if (t > 52) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(d, e, a, b, c, me2, 52); \ + if (t > 51) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(e, a, b, c, d, me2, 51); \ + if (t > 50) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(a, b, c, d, e, me2, 50); \ + if (t > 49) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(b, c, d, e, a, me2, 49); \ + if (t > 48) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(c, d, e, a, b, me2, 48); \ + if (t > 47) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(d, e, a, b, c, me2, 47); \ + if (t > 46) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(e, a, b, c, d, me2, 46); \ + if (t > 45) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(a, b, c, d, e, me2, 45); \ + if (t > 44) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(b, c, d, e, a, me2, 44); \ + if (t > 43) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(c, d, e, a, b, me2, 43); \ + if (t > 42) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(d, e, a, b, c, me2, 42); \ + if (t > 41) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(e, a, b, c, d, me2, 41); \ + if (t > 40) HASHCLASH_SHA1COMPRESS_ROUND3_STEP_BW(a, b, c, d, e, me2, 40); \ + if (t > 39) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(b, c, d, e, a, me2, 39); \ + if (t > 38) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(c, d, e, a, b, me2, 38); \ + if (t > 37) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(d, e, a, b, c, me2, 37); \ + if (t > 36) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(e, a, b, c, d, me2, 36); \ + if (t > 35) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(a, b, c, d, e, me2, 35); \ + if (t > 34) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(b, c, d, e, a, me2, 34); \ + if (t > 33) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(c, d, e, a, b, me2, 33); \ + if (t > 32) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(d, e, a, b, c, me2, 32); \ + if (t > 31) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(e, a, b, c, d, me2, 31); \ + if (t > 30) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(a, b, c, d, e, me2, 30); \ + if (t > 29) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(b, c, d, e, a, me2, 29); \ + if (t > 28) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(c, d, e, a, b, me2, 28); \ + if (t > 27) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(d, e, a, b, c, me2, 27); \ + if (t > 26) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(e, a, b, c, d, me2, 26); \ + if (t > 25) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(a, b, c, d, e, me2, 25); \ + if (t > 24) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(b, c, d, e, a, me2, 24); \ + if (t > 23) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(c, d, e, a, b, me2, 23); \ + if (t > 22) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(d, e, a, b, c, me2, 22); \ + if (t > 21) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(e, a, b, c, d, me2, 21); \ + if (t > 20) HASHCLASH_SHA1COMPRESS_ROUND2_STEP_BW(a, b, c, d, e, me2, 20); \ + if (t > 19) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(b, c, d, e, a, me2, 19); \ + if (t > 18) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(c, d, e, a, b, me2, 18); \ + if (t > 17) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(d, e, a, b, c, me2, 17); \ + if (t > 16) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(e, a, b, c, d, me2, 16); \ + if (t > 15) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(a, b, c, d, e, me2, 15); \ + if (t > 14) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(b, c, d, e, a, me2, 14); \ + if (t > 13) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(c, d, e, a, b, me2, 13); \ + if (t > 12) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(d, e, a, b, c, me2, 12); \ + if (t > 11) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(e, a, b, c, d, me2, 11); \ + if (t > 10) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(a, b, c, d, e, me2, 10); \ + if (t > 9) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(b, c, d, e, a, me2, 9); \ + if (t > 8) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(c, d, e, a, b, me2, 8); \ + if (t > 7) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(d, e, a, b, c, me2, 7); \ + if (t > 6) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(e, a, b, c, d, me2, 6); \ + if (t > 5) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(a, b, c, d, e, me2, 5); \ + if (t > 4) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(b, c, d, e, a, me2, 4); \ + if (t > 3) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(c, d, e, a, b, me2, 3); \ + if (t > 2) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(d, e, a, b, c, me2, 2); \ + if (t > 1) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(e, a, b, c, d, me2, 1); \ + if (t > 0) HASHCLASH_SHA1COMPRESS_ROUND1_STEP_BW(a, b, c, d, e, me2, 0); \ + ihvin[0] = a; ihvin[1] = b; ihvin[2] = c; ihvin[3] = d; ihvin[4] = e; \ + a = state[0]; b = state[1]; c = state[2]; d = state[3]; e = state[4]; \ + if (t <= 0) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, me2, 0); \ + if (t <= 1) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, me2, 1); \ + if (t <= 2) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, me2, 2); \ + if (t <= 3) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, me2, 3); \ + if (t <= 4) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, me2, 4); \ + if (t <= 5) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, me2, 5); \ + if (t <= 6) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, me2, 6); \ + if (t <= 7) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, me2, 7); \ + if (t <= 8) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, me2, 8); \ + if (t <= 9) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, me2, 9); \ + if (t <= 10) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, me2, 10); \ + if (t <= 11) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, me2, 11); \ + if (t <= 12) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, me2, 12); \ + if (t <= 13) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, me2, 13); \ + if (t <= 14) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, me2, 14); \ + if (t <= 15) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, me2, 15); \ + if (t <= 16) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, me2, 16); \ + if (t <= 17) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, me2, 17); \ + if (t <= 18) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, me2, 18); \ + if (t <= 19) HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, me2, 19); \ + if (t <= 20) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, me2, 20); \ + if (t <= 21) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, me2, 21); \ + if (t <= 22) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, me2, 22); \ + if (t <= 23) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, me2, 23); \ + if (t <= 24) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, me2, 24); \ + if (t <= 25) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, me2, 25); \ + if (t <= 26) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, me2, 26); \ + if (t <= 27) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, me2, 27); \ + if (t <= 28) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, me2, 28); \ + if (t <= 29) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, me2, 29); \ + if (t <= 30) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, me2, 30); \ + if (t <= 31) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, me2, 31); \ + if (t <= 32) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, me2, 32); \ + if (t <= 33) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, me2, 33); \ + if (t <= 34) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, me2, 34); \ + if (t <= 35) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, me2, 35); \ + if (t <= 36) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, me2, 36); \ + if (t <= 37) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, me2, 37); \ + if (t <= 38) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, me2, 38); \ + if (t <= 39) HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, me2, 39); \ + if (t <= 40) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, me2, 40); \ + if (t <= 41) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, me2, 41); \ + if (t <= 42) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, me2, 42); \ + if (t <= 43) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, me2, 43); \ + if (t <= 44) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, me2, 44); \ + if (t <= 45) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, me2, 45); \ + if (t <= 46) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, me2, 46); \ + if (t <= 47) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, me2, 47); \ + if (t <= 48) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, me2, 48); \ + if (t <= 49) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, me2, 49); \ + if (t <= 50) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, me2, 50); \ + if (t <= 51) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, me2, 51); \ + if (t <= 52) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, me2, 52); \ + if (t <= 53) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, me2, 53); \ + if (t <= 54) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, me2, 54); \ + if (t <= 55) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, me2, 55); \ + if (t <= 56) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, me2, 56); \ + if (t <= 57) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, me2, 57); \ + if (t <= 58) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, me2, 58); \ + if (t <= 59) HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, me2, 59); \ + if (t <= 60) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, me2, 60); \ + if (t <= 61) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, me2, 61); \ + if (t <= 62) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, me2, 62); \ + if (t <= 63) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, me2, 63); \ + if (t <= 64) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, me2, 64); \ + if (t <= 65) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, me2, 65); \ + if (t <= 66) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, me2, 66); \ + if (t <= 67) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, me2, 67); \ + if (t <= 68) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, me2, 68); \ + if (t <= 69) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, me2, 69); \ + if (t <= 70) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, me2, 70); \ + if (t <= 71) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, me2, 71); \ + if (t <= 72) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, me2, 72); \ + if (t <= 73) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, me2, 73); \ + if (t <= 74) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, me2, 74); \ + if (t <= 75) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, me2, 75); \ + if (t <= 76) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, me2, 76); \ + if (t <= 77) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, me2, 77); \ + if (t <= 78) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, me2, 78); \ + if (t <= 79) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, me2, 79); \ + ihvout[0] = ihvin[0] + a; ihvout[1] = ihvin[1] + b; ihvout[2] = ihvin[2] + c; ihvout[3] = ihvin[3] + d; ihvout[4] = ihvin[4] + e; \ +} + +SHA1_RECOMPRESS(0) +SHA1_RECOMPRESS(1) +SHA1_RECOMPRESS(2) +SHA1_RECOMPRESS(3) +SHA1_RECOMPRESS(4) +SHA1_RECOMPRESS(5) +SHA1_RECOMPRESS(6) +SHA1_RECOMPRESS(7) +SHA1_RECOMPRESS(8) +SHA1_RECOMPRESS(9) + +SHA1_RECOMPRESS(10) +SHA1_RECOMPRESS(11) +SHA1_RECOMPRESS(12) +SHA1_RECOMPRESS(13) +SHA1_RECOMPRESS(14) +SHA1_RECOMPRESS(15) +SHA1_RECOMPRESS(16) +SHA1_RECOMPRESS(17) +SHA1_RECOMPRESS(18) +SHA1_RECOMPRESS(19) + +SHA1_RECOMPRESS(20) +SHA1_RECOMPRESS(21) +SHA1_RECOMPRESS(22) +SHA1_RECOMPRESS(23) +SHA1_RECOMPRESS(24) +SHA1_RECOMPRESS(25) +SHA1_RECOMPRESS(26) +SHA1_RECOMPRESS(27) +SHA1_RECOMPRESS(28) +SHA1_RECOMPRESS(29) + +SHA1_RECOMPRESS(30) +SHA1_RECOMPRESS(31) +SHA1_RECOMPRESS(32) +SHA1_RECOMPRESS(33) +SHA1_RECOMPRESS(34) +SHA1_RECOMPRESS(35) +SHA1_RECOMPRESS(36) +SHA1_RECOMPRESS(37) +SHA1_RECOMPRESS(38) +SHA1_RECOMPRESS(39) + +SHA1_RECOMPRESS(40) +SHA1_RECOMPRESS(41) +SHA1_RECOMPRESS(42) +SHA1_RECOMPRESS(43) +SHA1_RECOMPRESS(44) +SHA1_RECOMPRESS(45) +SHA1_RECOMPRESS(46) +SHA1_RECOMPRESS(47) +SHA1_RECOMPRESS(48) +SHA1_RECOMPRESS(49) + +SHA1_RECOMPRESS(50) +SHA1_RECOMPRESS(51) +SHA1_RECOMPRESS(52) +SHA1_RECOMPRESS(53) +SHA1_RECOMPRESS(54) +SHA1_RECOMPRESS(55) +SHA1_RECOMPRESS(56) +SHA1_RECOMPRESS(57) +SHA1_RECOMPRESS(58) +SHA1_RECOMPRESS(59) + +SHA1_RECOMPRESS(60) +SHA1_RECOMPRESS(61) +SHA1_RECOMPRESS(62) +SHA1_RECOMPRESS(63) +SHA1_RECOMPRESS(64) +SHA1_RECOMPRESS(65) +SHA1_RECOMPRESS(66) +SHA1_RECOMPRESS(67) +SHA1_RECOMPRESS(68) +SHA1_RECOMPRESS(69) + +SHA1_RECOMPRESS(70) +SHA1_RECOMPRESS(71) +SHA1_RECOMPRESS(72) +SHA1_RECOMPRESS(73) +SHA1_RECOMPRESS(74) +SHA1_RECOMPRESS(75) +SHA1_RECOMPRESS(76) +SHA1_RECOMPRESS(77) +SHA1_RECOMPRESS(78) +SHA1_RECOMPRESS(79) + +sha1_recompression_type sha1_recompression_step[80] = +{ + sha1recompress_fast_0, sha1recompress_fast_1, sha1recompress_fast_2, sha1recompress_fast_3, sha1recompress_fast_4, sha1recompress_fast_5, sha1recompress_fast_6, sha1recompress_fast_7, sha1recompress_fast_8, sha1recompress_fast_9, + sha1recompress_fast_10, sha1recompress_fast_11, sha1recompress_fast_12, sha1recompress_fast_13, sha1recompress_fast_14, sha1recompress_fast_15, sha1recompress_fast_16, sha1recompress_fast_17, sha1recompress_fast_18, sha1recompress_fast_19, + sha1recompress_fast_20, sha1recompress_fast_21, sha1recompress_fast_22, sha1recompress_fast_23, sha1recompress_fast_24, sha1recompress_fast_25, sha1recompress_fast_26, sha1recompress_fast_27, sha1recompress_fast_28, sha1recompress_fast_29, + sha1recompress_fast_30, sha1recompress_fast_31, sha1recompress_fast_32, sha1recompress_fast_33, sha1recompress_fast_34, sha1recompress_fast_35, sha1recompress_fast_36, sha1recompress_fast_37, sha1recompress_fast_38, sha1recompress_fast_39, + sha1recompress_fast_40, sha1recompress_fast_41, sha1recompress_fast_42, sha1recompress_fast_43, sha1recompress_fast_44, sha1recompress_fast_45, sha1recompress_fast_46, sha1recompress_fast_47, sha1recompress_fast_48, sha1recompress_fast_49, + sha1recompress_fast_50, sha1recompress_fast_51, sha1recompress_fast_52, sha1recompress_fast_53, sha1recompress_fast_54, sha1recompress_fast_55, sha1recompress_fast_56, sha1recompress_fast_57, sha1recompress_fast_58, sha1recompress_fast_59, + sha1recompress_fast_60, sha1recompress_fast_61, sha1recompress_fast_62, sha1recompress_fast_63, sha1recompress_fast_64, sha1recompress_fast_65, sha1recompress_fast_66, sha1recompress_fast_67, sha1recompress_fast_68, sha1recompress_fast_69, + sha1recompress_fast_70, sha1recompress_fast_71, sha1recompress_fast_72, sha1recompress_fast_73, sha1recompress_fast_74, sha1recompress_fast_75, sha1recompress_fast_76, sha1recompress_fast_77, sha1recompress_fast_78, sha1recompress_fast_79, +}; + + + + + +void sha1_process(SHA1_CTX* ctx, const uint32_t block[16]) +{ + unsigned i, j; + uint32_t ubc_dv_mask[DVMASKSIZE]; + uint32_t ihvtmp[5]; + for (i=0; i < DVMASKSIZE; ++i) + ubc_dv_mask[i]=0; + ctx->ihv1[0] = ctx->ihv[0]; + ctx->ihv1[1] = ctx->ihv[1]; + ctx->ihv1[2] = ctx->ihv[2]; + ctx->ihv1[3] = ctx->ihv[3]; + ctx->ihv1[4] = ctx->ihv[4]; + memcpy(ctx->m1, block, 64); + sha1_message_expansion(ctx->m1); + if (ctx->detect_coll && ctx->ubc_check) + { + ubc_check(ctx->m1, ubc_dv_mask); + } + sha1_compression_states(ctx->ihv, ctx->m1, ctx->states); + if (ctx->detect_coll) + { + for (i = 0; sha1_dvs[i].dvType != 0; ++i) + { + if ((0 == ctx->ubc_check) || (((uint32_t)(1) << sha1_dvs[i].maskb) & ubc_dv_mask[sha1_dvs[i].maski])) + { + for (j = 0; j < 80; ++j) + ctx->m2[j] = ctx->m1[j] ^ sha1_dvs[i].dm[j]; + (sha1_recompression_step[sha1_dvs[i].testt])(ctx->ihv2, ihvtmp, ctx->m2, ctx->states[sha1_dvs[i].testt]); + // to verify SHA-1 collision detection code with collisions for reduced-step SHA-1 + if ((ihvtmp[0] == ctx->ihv[0] && ihvtmp[1] == ctx->ihv[1] && ihvtmp[2] == ctx->ihv[2] && ihvtmp[3] == ctx->ihv[3] && ihvtmp[4] == ctx->ihv[4]) + || (ctx->reduced_round_coll && ctx->ihv1[0] == ctx->ihv2[0] && ctx->ihv1[1] == ctx->ihv2[1] && ctx->ihv1[2] == ctx->ihv2[2] && ctx->ihv1[3] == ctx->ihv2[3] && ctx->ihv1[4] == ctx->ihv2[4])) + { + ctx->found_collision = 1; + // TODO: call callback + if (ctx->callback != NULL) + ctx->callback(ctx->total - 64, ctx->ihv1, ctx->ihv2, ctx->m1, ctx->m2); + + if (ctx->safe_hash) + { + sha1_compression_W(ctx->ihv, ctx->m1); + sha1_compression_W(ctx->ihv, ctx->m1); + } + + break; + } + } + } + } +} + + + + + +void swap_bytes(uint32_t val[16]) +{ + unsigned i; + for (i = 0; i < 16; ++i) + { + val[i] = ((val[i] << 8) & 0xFF00FF00) | ((val[i] >> 8) & 0xFF00FF); + val[i] = (val[i] << 16) | (val[i] >> 16); + } +} + +void SHA1DCInit(SHA1_CTX* ctx) +{ + static const union { unsigned char bytes[4]; uint32_t value; } endianness = { { 0, 1, 2, 3 } }; + static const uint32_t littleendian = 0x03020100; + ctx->total = 0; + ctx->ihv[0] = 0x67452301; + ctx->ihv[1] = 0xEFCDAB89; + ctx->ihv[2] = 0x98BADCFE; + ctx->ihv[3] = 0x10325476; + ctx->ihv[4] = 0xC3D2E1F0; + ctx->found_collision = 0; + ctx->safe_hash = 1; + ctx->ubc_check = 1; + ctx->detect_coll = 1; + ctx->reduced_round_coll = 0; + ctx->bigendian = (endianness.value != littleendian); + ctx->callback = NULL; +} + +void SHA1DCSetSafeHash(SHA1_CTX* ctx, int safehash) +{ + if (safehash) + ctx->safe_hash = 1; + else + ctx->safe_hash = 0; +} + + +void SHA1DCSetUseUBC(SHA1_CTX* ctx, int ubc_check) +{ + if (ubc_check) + ctx->ubc_check = 1; + else + ctx->ubc_check = 0; +} + +void SHA1DCSetUseDetectColl(SHA1_CTX* ctx, int detect_coll) +{ + if (detect_coll) + ctx->detect_coll = 1; + else + ctx->detect_coll = 0; +} + +void SHA1DCSetDetectReducedRoundCollision(SHA1_CTX* ctx, int reduced_round_coll) +{ + if (reduced_round_coll) + ctx->reduced_round_coll = 1; + else + ctx->reduced_round_coll = 0; +} + +void SHA1DCSetCallback(SHA1_CTX* ctx, collision_block_callback callback) +{ + ctx->callback = callback; +} + +void SHA1DCUpdate(SHA1_CTX* ctx, const char* buf, unsigned len) +{ + unsigned left, fill; + if (len == 0) + return; + + left = ctx->total & 63; + fill = 64 - left; + + if (left && len >= fill) + { + ctx->total += fill; + memcpy(ctx->buffer + left, buf, fill); + if (!ctx->bigendian) + swap_bytes((uint32_t*)(ctx->buffer)); + sha1_process(ctx, (uint32_t*)(ctx->buffer)); + buf += fill; + len -= fill; + left = 0; + } + while (len >= 64) + { + ctx->total += 64; + if (!ctx->bigendian) + { + memcpy(ctx->buffer, buf, 64); + swap_bytes((uint32_t*)(ctx->buffer)); + sha1_process(ctx, (uint32_t*)(ctx->buffer)); + } + else + sha1_process(ctx, (uint32_t*)(buf)); + buf += 64; + len -= 64; + } + if (len > 0) + { + ctx->total += len; + memcpy(ctx->buffer + left, buf, len); + } +} + +static const unsigned char sha1_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +int SHA1DCFinal(unsigned char output[20], SHA1_CTX *ctx) +{ + uint32_t last = ctx->total & 63; + uint32_t padn = (last < 56) ? (56 - last) : (120 - last); + uint64_t total; + SHA1DCUpdate(ctx, (const char*)(sha1_padding), padn); + + total = ctx->total - padn; + total <<= 3; + ctx->buffer[56] = (unsigned char)(total >> 56); + ctx->buffer[57] = (unsigned char)(total >> 48); + ctx->buffer[58] = (unsigned char)(total >> 40); + ctx->buffer[59] = (unsigned char)(total >> 32); + ctx->buffer[60] = (unsigned char)(total >> 24); + ctx->buffer[61] = (unsigned char)(total >> 16); + ctx->buffer[62] = (unsigned char)(total >> 8); + ctx->buffer[63] = (unsigned char)(total); + if (!ctx->bigendian) + swap_bytes((uint32_t*)(ctx->buffer)); + sha1_process(ctx, (uint32_t*)(ctx->buffer)); + output[0] = (unsigned char)(ctx->ihv[0] >> 24); + output[1] = (unsigned char)(ctx->ihv[0] >> 16); + output[2] = (unsigned char)(ctx->ihv[0] >> 8); + output[3] = (unsigned char)(ctx->ihv[0]); + output[4] = (unsigned char)(ctx->ihv[1] >> 24); + output[5] = (unsigned char)(ctx->ihv[1] >> 16); + output[6] = (unsigned char)(ctx->ihv[1] >> 8); + output[7] = (unsigned char)(ctx->ihv[1]); + output[8] = (unsigned char)(ctx->ihv[2] >> 24); + output[9] = (unsigned char)(ctx->ihv[2] >> 16); + output[10] = (unsigned char)(ctx->ihv[2] >> 8); + output[11] = (unsigned char)(ctx->ihv[2]); + output[12] = (unsigned char)(ctx->ihv[3] >> 24); + output[13] = (unsigned char)(ctx->ihv[3] >> 16); + output[14] = (unsigned char)(ctx->ihv[3] >> 8); + output[15] = (unsigned char)(ctx->ihv[3]); + output[16] = (unsigned char)(ctx->ihv[4] >> 24); + output[17] = (unsigned char)(ctx->ihv[4] >> 16); + output[18] = (unsigned char)(ctx->ihv[4] >> 8); + output[19] = (unsigned char)(ctx->ihv[4]); + return ctx->found_collision; +} diff --git a/src/hash/sha1dc/sha1.h b/src/hash/sha1dc/sha1.h new file mode 100644 index 000000000..8b522f9d2 --- /dev/null +++ b/src/hash/sha1dc/sha1.h @@ -0,0 +1,94 @@ +/*** +* Copyright 2017 Marc Stevens , Dan Shumow +* Distributed under the MIT Software License. +* See accompanying file LICENSE.txt or copy at +* https://opensource.org/licenses/MIT +***/ + +#include + +// uses SHA-1 message expansion to expand the first 16 words of W[] to 80 words +void sha1_message_expansion(uint32_t W[80]); + +// sha-1 compression function; first version takes a message block pre-parsed as 16 32-bit integers, second version takes an already expanded message) +void sha1_compression(uint32_t ihv[5], const uint32_t m[16]); +void sha1_compression_W(uint32_t ihv[5], const uint32_t W[80]); + +// same as sha1_compression_W, but additionally store intermediate states +// only stores states ii (the state between step ii-1 and step ii) when DOSTORESTATEii is defined in ubc_check.h +void sha1_compression_states(uint32_t ihv[5], const uint32_t W[80], uint32_t states[80][5]); + +// function type for sha1_recompression_step_T (uint32_t ihvin[5], uint32_t ihvout[5], const uint32_t me2[80], const uint32_t state[5]) +// where 0 <= T < 80 +// me2 is an expanded message (the expansion of an original message block XOR'ed with a disturbance vector's message block difference) +// state is the internal state (a,b,c,d,e) before step T of the SHA-1 compression function while processing the original message block +// the function will return: +// ihvin: the reconstructed input chaining value +// ihvout: the reconstructed output chaining value +typedef void(*sha1_recompression_type)(uint32_t*, uint32_t*, const uint32_t*, const uint32_t*); + +// table of sha1_recompression_step_0, ... , sha1_recompression_step_79 +extern sha1_recompression_type sha1_recompression_step[80]; + +// a callback function type that can be set to be called when a collision block has been found: +// void collision_block_callback(uint64_t byteoffset, const uint32_t ihvin1[5], const uint32_t ihvin2[5], const uint32_t m1[80], const uint32_t m2[80]) +typedef void(*collision_block_callback)(uint64_t, const uint32_t*, const uint32_t*, const uint32_t*, const uint32_t*); + +// the SHA-1 context +typedef struct { + uint64_t total; + uint32_t ihv[5]; + unsigned char buffer[64]; + int bigendian; + int found_collision; + int safe_hash; + int detect_coll; + int ubc_check; + int reduced_round_coll; + collision_block_callback callback; + + uint32_t ihv1[5]; + uint32_t ihv2[5]; + uint32_t m1[80]; + uint32_t m2[80]; + uint32_t states[80][5]; +} SHA1_CTX; + +// initialize SHA-1 context +void SHA1DCInit(SHA1_CTX*); + +// function to enable safe SHA-1 hashing: +// collision attacks are thwarted by hashing a detected near-collision block 3 times +// think of it as extending SHA-1 from 80-steps to 240-steps for such blocks: +// the best collision attacks against SHA-1 have complexity about 2^60, +// thus for 240-steps an immediate lower-bound for the best cryptanalytic attacks would 2^180 +// an attacker would be better off using a generic birthday search of complexity 2^80 +// +// enabling safe SHA-1 hashing will result in the correct SHA-1 hash for messages where no collision attack was detected +// but it will result in a different SHA-1 hash for messages where a collision attack was detected +// this will automatically invalidate SHA-1 based digital signature forgeries +// enabled by default +void SHA1DCSetSafeHash(SHA1_CTX*, int); + +// function to disable or enable the use of Unavoidable Bitconditions (provides a significant speed up) +// enabled by default +void SHA1DCSetUseUBC(SHA1_CTX*, int); + +// function to disable or enable the use of Collision Detection +// enabled by default +void SHA1DCSetUseDetectColl(SHA1_CTX* ctx, int detect_coll); + +// function to disable or enable the detection of reduced-round SHA-1 collisions +// disabled by default +void SHA1DCSetDetectReducedRoundCollision(SHA1_CTX*, int); + +// function to set a callback function, pass NULL to disable +// by default no callback set +void SHA1DCSetCallback(SHA1_CTX*, collision_block_callback); + +// update SHA-1 context with buffer contents +void SHA1DCUpdate(SHA1_CTX*, const char*, unsigned); + +// obtain SHA-1 hash from SHA-1 context +// returns: 0 = no collision detected, otherwise = collision found => warn user for active attack +int SHA1DCFinal(unsigned char[20], SHA1_CTX*); diff --git a/src/hash/sha1dc/ubc_check.c b/src/hash/sha1dc/ubc_check.c new file mode 100644 index 000000000..556aaf3c5 --- /dev/null +++ b/src/hash/sha1dc/ubc_check.c @@ -0,0 +1,361 @@ +/*** +* Copyright 2017 Marc Stevens , Dan Shumow +* Distributed under the MIT Software License. +* See accompanying file LICENSE.txt or copy at +* https://opensource.org/licenses/MIT +***/ + +// this file was generated by the 'parse_bitrel' program in the tools section +// using the data files from directory 'tools/data/3565' +// +// sha1_dvs contains a list of SHA-1 Disturbance Vectors (DV) to check +// dvType, dvK and dvB define the DV: I(K,B) or II(K,B) (see the paper) +// dm[80] is the expanded message block XOR-difference defined by the DV +// testt is the step to do the recompression from for collision detection +// maski and maskb define the bit to check for each DV in the dvmask returned by ubc_check +// +// ubc_check takes as input an expanded message block and verifies the unavoidable bitconditions for all listed DVs +// it returns a dvmask where each bit belonging to a DV is set if all unavoidable bitconditions for that DV have been met +// thus one needs to do the recompression check for each DV that has its bit set +// +// ubc_check is programmatically generated and the unavoidable bitconditions have been hardcoded +// a directly verifiable version named ubc_check_verify can be found in ubc_check_verify.c +// ubc_check has been verified against ubc_check_verify using the 'ubc_check_test' program in the tools section + +#include +#include "ubc_check.h" + +static const uint32_t DV_I_43_0_bit = (uint32_t)(1) << 0; +static const uint32_t DV_I_44_0_bit = (uint32_t)(1) << 1; +static const uint32_t DV_I_45_0_bit = (uint32_t)(1) << 2; +static const uint32_t DV_I_46_0_bit = (uint32_t)(1) << 3; +static const uint32_t DV_I_46_2_bit = (uint32_t)(1) << 4; +static const uint32_t DV_I_47_0_bit = (uint32_t)(1) << 5; +static const uint32_t DV_I_47_2_bit = (uint32_t)(1) << 6; +static const uint32_t DV_I_48_0_bit = (uint32_t)(1) << 7; +static const uint32_t DV_I_48_2_bit = (uint32_t)(1) << 8; +static const uint32_t DV_I_49_0_bit = (uint32_t)(1) << 9; +static const uint32_t DV_I_49_2_bit = (uint32_t)(1) << 10; +static const uint32_t DV_I_50_0_bit = (uint32_t)(1) << 11; +static const uint32_t DV_I_50_2_bit = (uint32_t)(1) << 12; +static const uint32_t DV_I_51_0_bit = (uint32_t)(1) << 13; +static const uint32_t DV_I_51_2_bit = (uint32_t)(1) << 14; +static const uint32_t DV_I_52_0_bit = (uint32_t)(1) << 15; +static const uint32_t DV_II_45_0_bit = (uint32_t)(1) << 16; +static const uint32_t DV_II_46_0_bit = (uint32_t)(1) << 17; +static const uint32_t DV_II_46_2_bit = (uint32_t)(1) << 18; +static const uint32_t DV_II_47_0_bit = (uint32_t)(1) << 19; +static const uint32_t DV_II_48_0_bit = (uint32_t)(1) << 20; +static const uint32_t DV_II_49_0_bit = (uint32_t)(1) << 21; +static const uint32_t DV_II_49_2_bit = (uint32_t)(1) << 22; +static const uint32_t DV_II_50_0_bit = (uint32_t)(1) << 23; +static const uint32_t DV_II_50_2_bit = (uint32_t)(1) << 24; +static const uint32_t DV_II_51_0_bit = (uint32_t)(1) << 25; +static const uint32_t DV_II_51_2_bit = (uint32_t)(1) << 26; +static const uint32_t DV_II_52_0_bit = (uint32_t)(1) << 27; +static const uint32_t DV_II_53_0_bit = (uint32_t)(1) << 28; +static const uint32_t DV_II_54_0_bit = (uint32_t)(1) << 29; +static const uint32_t DV_II_55_0_bit = (uint32_t)(1) << 30; +static const uint32_t DV_II_56_0_bit = (uint32_t)(1) << 31; + +dv_info_t sha1_dvs[] = +{ + {1,43,0,58,0,0, { 0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202,0x00000018,0x00000164,0x00000408,0x800000e6,0x8000004c,0x00000803,0x80000161,0x80000599 } } +, {1,44,0,58,0,1, { 0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202,0x00000018,0x00000164,0x00000408,0x800000e6,0x8000004c,0x00000803,0x80000161 } } +, {1,45,0,58,0,2, { 0xf4000014,0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202,0x00000018,0x00000164,0x00000408,0x800000e6,0x8000004c,0x00000803 } } +, {1,46,0,58,0,3, { 0x2c000010,0xf4000014,0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202,0x00000018,0x00000164,0x00000408,0x800000e6,0x8000004c } } +, {1,46,2,58,0,4, { 0xb0000040,0xd0000053,0xd0000022,0x20000000,0x60000032,0x60000043,0x20000040,0xe0000042,0x60000002,0x80000001,0x00000020,0x00000003,0x40000052,0x40000040,0xe0000052,0xa0000000,0x80000040,0x20000001,0x20000060,0x80000001,0x40000042,0xc0000043,0x40000022,0x00000003,0x40000042,0xc0000043,0xc0000022,0x00000001,0x40000002,0xc0000043,0x40000062,0x80000001,0x40000042,0x40000042,0x40000002,0x00000002,0x00000040,0x80000002,0x80000000,0x80000002,0x80000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000000,0x00000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000101,0x00000009,0x00000012,0x00000202,0x0000001a,0x00000124,0x0000040c,0x00000026,0x0000004a,0x0000080a,0x00000060,0x00000590,0x00001020,0x0000039a,0x00000132 } } +, {1,47,0,58,0,5, { 0xc8000010,0x2c000010,0xf4000014,0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202,0x00000018,0x00000164,0x00000408,0x800000e6 } } +, {1,47,2,58,0,6, { 0x20000043,0xb0000040,0xd0000053,0xd0000022,0x20000000,0x60000032,0x60000043,0x20000040,0xe0000042,0x60000002,0x80000001,0x00000020,0x00000003,0x40000052,0x40000040,0xe0000052,0xa0000000,0x80000040,0x20000001,0x20000060,0x80000001,0x40000042,0xc0000043,0x40000022,0x00000003,0x40000042,0xc0000043,0xc0000022,0x00000001,0x40000002,0xc0000043,0x40000062,0x80000001,0x40000042,0x40000042,0x40000002,0x00000002,0x00000040,0x80000002,0x80000000,0x80000002,0x80000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000000,0x00000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000101,0x00000009,0x00000012,0x00000202,0x0000001a,0x00000124,0x0000040c,0x00000026,0x0000004a,0x0000080a,0x00000060,0x00000590,0x00001020,0x0000039a } } +, {1,48,0,58,0,7, { 0xb800000a,0xc8000010,0x2c000010,0xf4000014,0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202,0x00000018,0x00000164,0x00000408 } } +, {1,48,2,58,0,8, { 0xe000002a,0x20000043,0xb0000040,0xd0000053,0xd0000022,0x20000000,0x60000032,0x60000043,0x20000040,0xe0000042,0x60000002,0x80000001,0x00000020,0x00000003,0x40000052,0x40000040,0xe0000052,0xa0000000,0x80000040,0x20000001,0x20000060,0x80000001,0x40000042,0xc0000043,0x40000022,0x00000003,0x40000042,0xc0000043,0xc0000022,0x00000001,0x40000002,0xc0000043,0x40000062,0x80000001,0x40000042,0x40000042,0x40000002,0x00000002,0x00000040,0x80000002,0x80000000,0x80000002,0x80000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000000,0x00000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000101,0x00000009,0x00000012,0x00000202,0x0000001a,0x00000124,0x0000040c,0x00000026,0x0000004a,0x0000080a,0x00000060,0x00000590,0x00001020 } } +, {1,49,0,58,0,9, { 0x18000000,0xb800000a,0xc8000010,0x2c000010,0xf4000014,0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202,0x00000018,0x00000164 } } +, {1,49,2,58,0,10, { 0x60000000,0xe000002a,0x20000043,0xb0000040,0xd0000053,0xd0000022,0x20000000,0x60000032,0x60000043,0x20000040,0xe0000042,0x60000002,0x80000001,0x00000020,0x00000003,0x40000052,0x40000040,0xe0000052,0xa0000000,0x80000040,0x20000001,0x20000060,0x80000001,0x40000042,0xc0000043,0x40000022,0x00000003,0x40000042,0xc0000043,0xc0000022,0x00000001,0x40000002,0xc0000043,0x40000062,0x80000001,0x40000042,0x40000042,0x40000002,0x00000002,0x00000040,0x80000002,0x80000000,0x80000002,0x80000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000000,0x00000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000101,0x00000009,0x00000012,0x00000202,0x0000001a,0x00000124,0x0000040c,0x00000026,0x0000004a,0x0000080a,0x00000060,0x00000590 } } +, {1,50,0,65,0,11, { 0x0800000c,0x18000000,0xb800000a,0xc8000010,0x2c000010,0xf4000014,0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202,0x00000018 } } +, {1,50,2,65,0,12, { 0x20000030,0x60000000,0xe000002a,0x20000043,0xb0000040,0xd0000053,0xd0000022,0x20000000,0x60000032,0x60000043,0x20000040,0xe0000042,0x60000002,0x80000001,0x00000020,0x00000003,0x40000052,0x40000040,0xe0000052,0xa0000000,0x80000040,0x20000001,0x20000060,0x80000001,0x40000042,0xc0000043,0x40000022,0x00000003,0x40000042,0xc0000043,0xc0000022,0x00000001,0x40000002,0xc0000043,0x40000062,0x80000001,0x40000042,0x40000042,0x40000002,0x00000002,0x00000040,0x80000002,0x80000000,0x80000002,0x80000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000000,0x00000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000101,0x00000009,0x00000012,0x00000202,0x0000001a,0x00000124,0x0000040c,0x00000026,0x0000004a,0x0000080a,0x00000060 } } +, {1,51,0,65,0,13, { 0xe8000000,0x0800000c,0x18000000,0xb800000a,0xc8000010,0x2c000010,0xf4000014,0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202 } } +, {1,51,2,65,0,14, { 0xa0000003,0x20000030,0x60000000,0xe000002a,0x20000043,0xb0000040,0xd0000053,0xd0000022,0x20000000,0x60000032,0x60000043,0x20000040,0xe0000042,0x60000002,0x80000001,0x00000020,0x00000003,0x40000052,0x40000040,0xe0000052,0xa0000000,0x80000040,0x20000001,0x20000060,0x80000001,0x40000042,0xc0000043,0x40000022,0x00000003,0x40000042,0xc0000043,0xc0000022,0x00000001,0x40000002,0xc0000043,0x40000062,0x80000001,0x40000042,0x40000042,0x40000002,0x00000002,0x00000040,0x80000002,0x80000000,0x80000002,0x80000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000000,0x00000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000101,0x00000009,0x00000012,0x00000202,0x0000001a,0x00000124,0x0000040c,0x00000026,0x0000004a,0x0000080a } } +, {1,52,0,65,0,15, { 0x04000010,0xe8000000,0x0800000c,0x18000000,0xb800000a,0xc8000010,0x2c000010,0xf4000014,0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012 } } +, {2,45,0,58,0,16, { 0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107,0x00000089,0x00000014,0x8000024b,0x0000011b,0x8000016d,0x8000041a,0x000002e4,0x80000054,0x00000967 } } +, {2,46,0,58,0,17, { 0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107,0x00000089,0x00000014,0x8000024b,0x0000011b,0x8000016d,0x8000041a,0x000002e4,0x80000054 } } +, {2,46,2,58,0,18, { 0x90000070,0xb0000053,0x30000008,0x00000043,0xd0000072,0xb0000010,0xf0000062,0xc0000042,0x00000030,0xe0000042,0x20000060,0xe0000041,0x20000050,0xc0000041,0xe0000072,0xa0000003,0xc0000012,0x60000041,0xc0000032,0x20000001,0xc0000002,0xe0000042,0x60000042,0x80000002,0x00000000,0x00000000,0x80000000,0x00000002,0x00000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000001,0x00000060,0x80000003,0x40000002,0xc0000040,0xc0000002,0x80000000,0x80000000,0x80000002,0x00000040,0x00000002,0x80000000,0x80000000,0x80000000,0x00000002,0x00000040,0x00000000,0x80000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000105,0x00000089,0x00000016,0x0000020b,0x0000011b,0x0000012d,0x0000041e,0x00000224,0x00000050,0x0000092e,0x0000046c,0x000005b6,0x0000106a,0x00000b90,0x00000152 } } +, {2,47,0,58,0,19, { 0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107,0x00000089,0x00000014,0x8000024b,0x0000011b,0x8000016d,0x8000041a,0x000002e4 } } +, {2,48,0,58,0,20, { 0xbc00001a,0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107,0x00000089,0x00000014,0x8000024b,0x0000011b,0x8000016d,0x8000041a } } +, {2,49,0,58,0,21, { 0x3c000004,0xbc00001a,0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107,0x00000089,0x00000014,0x8000024b,0x0000011b,0x8000016d } } +, {2,49,2,58,0,22, { 0xf0000010,0xf000006a,0x80000040,0x90000070,0xb0000053,0x30000008,0x00000043,0xd0000072,0xb0000010,0xf0000062,0xc0000042,0x00000030,0xe0000042,0x20000060,0xe0000041,0x20000050,0xc0000041,0xe0000072,0xa0000003,0xc0000012,0x60000041,0xc0000032,0x20000001,0xc0000002,0xe0000042,0x60000042,0x80000002,0x00000000,0x00000000,0x80000000,0x00000002,0x00000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000001,0x00000060,0x80000003,0x40000002,0xc0000040,0xc0000002,0x80000000,0x80000000,0x80000002,0x00000040,0x00000002,0x80000000,0x80000000,0x80000000,0x00000002,0x00000040,0x00000000,0x80000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000105,0x00000089,0x00000016,0x0000020b,0x0000011b,0x0000012d,0x0000041e,0x00000224,0x00000050,0x0000092e,0x0000046c,0x000005b6 } } +, {2,50,0,65,0,23, { 0xb400001c,0x3c000004,0xbc00001a,0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107,0x00000089,0x00000014,0x8000024b,0x0000011b } } +, {2,50,2,65,0,24, { 0xd0000072,0xf0000010,0xf000006a,0x80000040,0x90000070,0xb0000053,0x30000008,0x00000043,0xd0000072,0xb0000010,0xf0000062,0xc0000042,0x00000030,0xe0000042,0x20000060,0xe0000041,0x20000050,0xc0000041,0xe0000072,0xa0000003,0xc0000012,0x60000041,0xc0000032,0x20000001,0xc0000002,0xe0000042,0x60000042,0x80000002,0x00000000,0x00000000,0x80000000,0x00000002,0x00000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000001,0x00000060,0x80000003,0x40000002,0xc0000040,0xc0000002,0x80000000,0x80000000,0x80000002,0x00000040,0x00000002,0x80000000,0x80000000,0x80000000,0x00000002,0x00000040,0x00000000,0x80000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000105,0x00000089,0x00000016,0x0000020b,0x0000011b,0x0000012d,0x0000041e,0x00000224,0x00000050,0x0000092e,0x0000046c } } +, {2,51,0,65,0,25, { 0xc0000010,0xb400001c,0x3c000004,0xbc00001a,0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107,0x00000089,0x00000014,0x8000024b } } +, {2,51,2,65,0,26, { 0x00000043,0xd0000072,0xf0000010,0xf000006a,0x80000040,0x90000070,0xb0000053,0x30000008,0x00000043,0xd0000072,0xb0000010,0xf0000062,0xc0000042,0x00000030,0xe0000042,0x20000060,0xe0000041,0x20000050,0xc0000041,0xe0000072,0xa0000003,0xc0000012,0x60000041,0xc0000032,0x20000001,0xc0000002,0xe0000042,0x60000042,0x80000002,0x00000000,0x00000000,0x80000000,0x00000002,0x00000040,0x00000000,0x80000040,0x80000000,0x00000040,0x80000001,0x00000060,0x80000003,0x40000002,0xc0000040,0xc0000002,0x80000000,0x80000000,0x80000002,0x00000040,0x00000002,0x80000000,0x80000000,0x80000000,0x00000002,0x00000040,0x00000000,0x80000040,0x80000002,0x00000000,0x80000000,0x80000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000004,0x00000080,0x00000004,0x00000009,0x00000105,0x00000089,0x00000016,0x0000020b,0x0000011b,0x0000012d,0x0000041e,0x00000224,0x00000050,0x0000092e } } +, {2,52,0,65,0,27, { 0x0c000002,0xc0000010,0xb400001c,0x3c000004,0xbc00001a,0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107,0x00000089,0x00000014 } } +, {2,53,0,65,0,28, { 0xcc000014,0x0c000002,0xc0000010,0xb400001c,0x3c000004,0xbc00001a,0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107,0x00000089 } } +, {2,54,0,65,0,29, { 0x0400001c,0xcc000014,0x0c000002,0xc0000010,0xb400001c,0x3c000004,0xbc00001a,0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b,0x80000107 } } +, {2,55,0,65,0,30, { 0x00000010,0x0400001c,0xcc000014,0x0c000002,0xc0000010,0xb400001c,0x3c000004,0xbc00001a,0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046,0x4000004b } } +, {2,56,0,65,0,31, { 0x2600001a,0x00000010,0x0400001c,0xcc000014,0x0c000002,0xc0000010,0xb400001c,0x3c000004,0xbc00001a,0x20000010,0x2400001c,0xec000014,0x0c000002,0xc0000010,0xb400001c,0x2c000004,0xbc000018,0xb0000010,0x0000000c,0xb8000010,0x08000018,0x78000010,0x08000014,0x70000010,0xb800001c,0xe8000000,0xb0000004,0x58000010,0xb000000c,0x48000000,0xb0000000,0xb8000010,0x98000010,0xa0000000,0x00000000,0x00000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0x20000000,0x00000010,0x60000000,0x00000018,0xe0000000,0x90000000,0x30000010,0xb0000000,0x20000000,0x20000000,0xa0000000,0x00000010,0x80000000,0x20000000,0x20000000,0x20000000,0x80000000,0x00000010,0x00000000,0x20000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000041,0x40000022,0x80000005,0xc0000082,0xc0000046 } } +, {0,0,0,0,0,0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}} +}; +void ubc_check(const uint32_t W[80], uint32_t dvmask[1]) +{ + uint32_t mask = ~((uint32_t)(0)); + mask &= (((((W[44]^W[45])>>29)&1)-1) | ~(DV_I_48_0_bit|DV_I_51_0_bit|DV_I_52_0_bit|DV_II_45_0_bit|DV_II_46_0_bit|DV_II_50_0_bit|DV_II_51_0_bit)); + mask &= (((((W[49]^W[50])>>29)&1)-1) | ~(DV_I_46_0_bit|DV_II_45_0_bit|DV_II_50_0_bit|DV_II_51_0_bit|DV_II_55_0_bit|DV_II_56_0_bit)); + mask &= (((((W[48]^W[49])>>29)&1)-1) | ~(DV_I_45_0_bit|DV_I_52_0_bit|DV_II_49_0_bit|DV_II_50_0_bit|DV_II_54_0_bit|DV_II_55_0_bit)); + mask &= ((((W[47]^(W[50]>>25))&(1<<4))-(1<<4)) | ~(DV_I_47_0_bit|DV_I_49_0_bit|DV_I_51_0_bit|DV_II_45_0_bit|DV_II_51_0_bit|DV_II_56_0_bit)); + mask &= (((((W[47]^W[48])>>29)&1)-1) | ~(DV_I_44_0_bit|DV_I_51_0_bit|DV_II_48_0_bit|DV_II_49_0_bit|DV_II_53_0_bit|DV_II_54_0_bit)); + mask &= (((((W[46]>>4)^(W[49]>>29))&1)-1) | ~(DV_I_46_0_bit|DV_I_48_0_bit|DV_I_50_0_bit|DV_I_52_0_bit|DV_II_50_0_bit|DV_II_55_0_bit)); + mask &= (((((W[46]^W[47])>>29)&1)-1) | ~(DV_I_43_0_bit|DV_I_50_0_bit|DV_II_47_0_bit|DV_II_48_0_bit|DV_II_52_0_bit|DV_II_53_0_bit)); + mask &= (((((W[45]>>4)^(W[48]>>29))&1)-1) | ~(DV_I_45_0_bit|DV_I_47_0_bit|DV_I_49_0_bit|DV_I_51_0_bit|DV_II_49_0_bit|DV_II_54_0_bit)); + mask &= (((((W[45]^W[46])>>29)&1)-1) | ~(DV_I_49_0_bit|DV_I_52_0_bit|DV_II_46_0_bit|DV_II_47_0_bit|DV_II_51_0_bit|DV_II_52_0_bit)); + mask &= (((((W[44]>>4)^(W[47]>>29))&1)-1) | ~(DV_I_44_0_bit|DV_I_46_0_bit|DV_I_48_0_bit|DV_I_50_0_bit|DV_II_48_0_bit|DV_II_53_0_bit)); + mask &= (((((W[43]>>4)^(W[46]>>29))&1)-1) | ~(DV_I_43_0_bit|DV_I_45_0_bit|DV_I_47_0_bit|DV_I_49_0_bit|DV_II_47_0_bit|DV_II_52_0_bit)); + mask &= (((((W[43]^W[44])>>29)&1)-1) | ~(DV_I_47_0_bit|DV_I_50_0_bit|DV_I_51_0_bit|DV_II_45_0_bit|DV_II_49_0_bit|DV_II_50_0_bit)); + mask &= (((((W[42]>>4)^(W[45]>>29))&1)-1) | ~(DV_I_44_0_bit|DV_I_46_0_bit|DV_I_48_0_bit|DV_I_52_0_bit|DV_II_46_0_bit|DV_II_51_0_bit)); + mask &= (((((W[41]>>4)^(W[44]>>29))&1)-1) | ~(DV_I_43_0_bit|DV_I_45_0_bit|DV_I_47_0_bit|DV_I_51_0_bit|DV_II_45_0_bit|DV_II_50_0_bit)); + mask &= (((((W[40]^W[41])>>29)&1)-1) | ~(DV_I_44_0_bit|DV_I_47_0_bit|DV_I_48_0_bit|DV_II_46_0_bit|DV_II_47_0_bit|DV_II_56_0_bit)); + mask &= (((((W[54]^W[55])>>29)&1)-1) | ~(DV_I_51_0_bit|DV_II_47_0_bit|DV_II_50_0_bit|DV_II_55_0_bit|DV_II_56_0_bit)); + mask &= (((((W[53]^W[54])>>29)&1)-1) | ~(DV_I_50_0_bit|DV_II_46_0_bit|DV_II_49_0_bit|DV_II_54_0_bit|DV_II_55_0_bit)); + mask &= (((((W[52]^W[53])>>29)&1)-1) | ~(DV_I_49_0_bit|DV_II_45_0_bit|DV_II_48_0_bit|DV_II_53_0_bit|DV_II_54_0_bit)); + mask &= ((((W[50]^(W[53]>>25))&(1<<4))-(1<<4)) | ~(DV_I_50_0_bit|DV_I_52_0_bit|DV_II_46_0_bit|DV_II_48_0_bit|DV_II_54_0_bit)); + mask &= (((((W[50]^W[51])>>29)&1)-1) | ~(DV_I_47_0_bit|DV_II_46_0_bit|DV_II_51_0_bit|DV_II_52_0_bit|DV_II_56_0_bit)); + mask &= ((((W[49]^(W[52]>>25))&(1<<4))-(1<<4)) | ~(DV_I_49_0_bit|DV_I_51_0_bit|DV_II_45_0_bit|DV_II_47_0_bit|DV_II_53_0_bit)); + mask &= ((((W[48]^(W[51]>>25))&(1<<4))-(1<<4)) | ~(DV_I_48_0_bit|DV_I_50_0_bit|DV_I_52_0_bit|DV_II_46_0_bit|DV_II_52_0_bit)); + mask &= (((((W[42]^W[43])>>29)&1)-1) | ~(DV_I_46_0_bit|DV_I_49_0_bit|DV_I_50_0_bit|DV_II_48_0_bit|DV_II_49_0_bit)); + mask &= (((((W[41]^W[42])>>29)&1)-1) | ~(DV_I_45_0_bit|DV_I_48_0_bit|DV_I_49_0_bit|DV_II_47_0_bit|DV_II_48_0_bit)); + mask &= (((((W[40]>>4)^(W[43]>>29))&1)-1) | ~(DV_I_44_0_bit|DV_I_46_0_bit|DV_I_50_0_bit|DV_II_49_0_bit|DV_II_56_0_bit)); + mask &= (((((W[39]>>4)^(W[42]>>29))&1)-1) | ~(DV_I_43_0_bit|DV_I_45_0_bit|DV_I_49_0_bit|DV_II_48_0_bit|DV_II_55_0_bit)); + if (mask & (DV_I_44_0_bit|DV_I_48_0_bit|DV_II_47_0_bit|DV_II_54_0_bit|DV_II_56_0_bit)) + mask &= (((((W[38]>>4)^(W[41]>>29))&1)-1) | ~(DV_I_44_0_bit|DV_I_48_0_bit|DV_II_47_0_bit|DV_II_54_0_bit|DV_II_56_0_bit)); + mask &= (((((W[37]>>4)^(W[40]>>29))&1)-1) | ~(DV_I_43_0_bit|DV_I_47_0_bit|DV_II_46_0_bit|DV_II_53_0_bit|DV_II_55_0_bit)); + if (mask & (DV_I_52_0_bit|DV_II_48_0_bit|DV_II_51_0_bit|DV_II_56_0_bit)) + mask &= (((((W[55]^W[56])>>29)&1)-1) | ~(DV_I_52_0_bit|DV_II_48_0_bit|DV_II_51_0_bit|DV_II_56_0_bit)); + if (mask & (DV_I_52_0_bit|DV_II_48_0_bit|DV_II_50_0_bit|DV_II_56_0_bit)) + mask &= ((((W[52]^(W[55]>>25))&(1<<4))-(1<<4)) | ~(DV_I_52_0_bit|DV_II_48_0_bit|DV_II_50_0_bit|DV_II_56_0_bit)); + if (mask & (DV_I_51_0_bit|DV_II_47_0_bit|DV_II_49_0_bit|DV_II_55_0_bit)) + mask &= ((((W[51]^(W[54]>>25))&(1<<4))-(1<<4)) | ~(DV_I_51_0_bit|DV_II_47_0_bit|DV_II_49_0_bit|DV_II_55_0_bit)); + if (mask & (DV_I_48_0_bit|DV_II_47_0_bit|DV_II_52_0_bit|DV_II_53_0_bit)) + mask &= (((((W[51]^W[52])>>29)&1)-1) | ~(DV_I_48_0_bit|DV_II_47_0_bit|DV_II_52_0_bit|DV_II_53_0_bit)); + if (mask & (DV_I_46_0_bit|DV_I_49_0_bit|DV_II_45_0_bit|DV_II_48_0_bit)) + mask &= (((((W[36]>>4)^(W[40]>>29))&1)-1) | ~(DV_I_46_0_bit|DV_I_49_0_bit|DV_II_45_0_bit|DV_II_48_0_bit)); + if (mask & (DV_I_52_0_bit|DV_II_48_0_bit|DV_II_49_0_bit)) + mask &= ((0-(((W[53]^W[56])>>29)&1)) | ~(DV_I_52_0_bit|DV_II_48_0_bit|DV_II_49_0_bit)); + if (mask & (DV_I_50_0_bit|DV_II_46_0_bit|DV_II_47_0_bit)) + mask &= ((0-(((W[51]^W[54])>>29)&1)) | ~(DV_I_50_0_bit|DV_II_46_0_bit|DV_II_47_0_bit)); + if (mask & (DV_I_49_0_bit|DV_I_51_0_bit|DV_II_45_0_bit)) + mask &= ((0-(((W[50]^W[52])>>29)&1)) | ~(DV_I_49_0_bit|DV_I_51_0_bit|DV_II_45_0_bit)); + if (mask & (DV_I_48_0_bit|DV_I_50_0_bit|DV_I_52_0_bit)) + mask &= ((0-(((W[49]^W[51])>>29)&1)) | ~(DV_I_48_0_bit|DV_I_50_0_bit|DV_I_52_0_bit)); + if (mask & (DV_I_47_0_bit|DV_I_49_0_bit|DV_I_51_0_bit)) + mask &= ((0-(((W[48]^W[50])>>29)&1)) | ~(DV_I_47_0_bit|DV_I_49_0_bit|DV_I_51_0_bit)); + if (mask & (DV_I_46_0_bit|DV_I_48_0_bit|DV_I_50_0_bit)) + mask &= ((0-(((W[47]^W[49])>>29)&1)) | ~(DV_I_46_0_bit|DV_I_48_0_bit|DV_I_50_0_bit)); + if (mask & (DV_I_45_0_bit|DV_I_47_0_bit|DV_I_49_0_bit)) + mask &= ((0-(((W[46]^W[48])>>29)&1)) | ~(DV_I_45_0_bit|DV_I_47_0_bit|DV_I_49_0_bit)); + mask &= ((((W[45]^W[47])&(1<<6))-(1<<6)) | ~(DV_I_47_2_bit|DV_I_49_2_bit|DV_I_51_2_bit)); + if (mask & (DV_I_44_0_bit|DV_I_46_0_bit|DV_I_48_0_bit)) + mask &= ((0-(((W[45]^W[47])>>29)&1)) | ~(DV_I_44_0_bit|DV_I_46_0_bit|DV_I_48_0_bit)); + mask &= (((((W[44]^W[46])>>6)&1)-1) | ~(DV_I_46_2_bit|DV_I_48_2_bit|DV_I_50_2_bit)); + if (mask & (DV_I_43_0_bit|DV_I_45_0_bit|DV_I_47_0_bit)) + mask &= ((0-(((W[44]^W[46])>>29)&1)) | ~(DV_I_43_0_bit|DV_I_45_0_bit|DV_I_47_0_bit)); + mask &= ((0-((W[41]^(W[42]>>5))&(1<<1))) | ~(DV_I_48_2_bit|DV_II_46_2_bit|DV_II_51_2_bit)); + mask &= ((0-((W[40]^(W[41]>>5))&(1<<1))) | ~(DV_I_47_2_bit|DV_I_51_2_bit|DV_II_50_2_bit)); + if (mask & (DV_I_44_0_bit|DV_I_46_0_bit|DV_II_56_0_bit)) + mask &= ((0-(((W[40]^W[42])>>4)&1)) | ~(DV_I_44_0_bit|DV_I_46_0_bit|DV_II_56_0_bit)); + mask &= ((0-((W[39]^(W[40]>>5))&(1<<1))) | ~(DV_I_46_2_bit|DV_I_50_2_bit|DV_II_49_2_bit)); + if (mask & (DV_I_43_0_bit|DV_I_45_0_bit|DV_II_55_0_bit)) + mask &= ((0-(((W[39]^W[41])>>4)&1)) | ~(DV_I_43_0_bit|DV_I_45_0_bit|DV_II_55_0_bit)); + if (mask & (DV_I_44_0_bit|DV_II_54_0_bit|DV_II_56_0_bit)) + mask &= ((0-(((W[38]^W[40])>>4)&1)) | ~(DV_I_44_0_bit|DV_II_54_0_bit|DV_II_56_0_bit)); + if (mask & (DV_I_43_0_bit|DV_II_53_0_bit|DV_II_55_0_bit)) + mask &= ((0-(((W[37]^W[39])>>4)&1)) | ~(DV_I_43_0_bit|DV_II_53_0_bit|DV_II_55_0_bit)); + mask &= ((0-((W[36]^(W[37]>>5))&(1<<1))) | ~(DV_I_47_2_bit|DV_I_50_2_bit|DV_II_46_2_bit)); + if (mask & (DV_I_45_0_bit|DV_I_48_0_bit|DV_II_47_0_bit)) + mask &= (((((W[35]>>4)^(W[39]>>29))&1)-1) | ~(DV_I_45_0_bit|DV_I_48_0_bit|DV_II_47_0_bit)); + if (mask & (DV_I_48_0_bit|DV_II_48_0_bit)) + mask &= ((0-((W[63]^(W[64]>>5))&(1<<0))) | ~(DV_I_48_0_bit|DV_II_48_0_bit)); + if (mask & (DV_I_45_0_bit|DV_II_45_0_bit)) + mask &= ((0-((W[63]^(W[64]>>5))&(1<<1))) | ~(DV_I_45_0_bit|DV_II_45_0_bit)); + if (mask & (DV_I_47_0_bit|DV_II_47_0_bit)) + mask &= ((0-((W[62]^(W[63]>>5))&(1<<0))) | ~(DV_I_47_0_bit|DV_II_47_0_bit)); + if (mask & (DV_I_46_0_bit|DV_II_46_0_bit)) + mask &= ((0-((W[61]^(W[62]>>5))&(1<<0))) | ~(DV_I_46_0_bit|DV_II_46_0_bit)); + mask &= ((0-((W[61]^(W[62]>>5))&(1<<2))) | ~(DV_I_46_2_bit|DV_II_46_2_bit)); + if (mask & (DV_I_45_0_bit|DV_II_45_0_bit)) + mask &= ((0-((W[60]^(W[61]>>5))&(1<<0))) | ~(DV_I_45_0_bit|DV_II_45_0_bit)); + if (mask & (DV_II_51_0_bit|DV_II_54_0_bit)) + mask &= (((((W[58]^W[59])>>29)&1)-1) | ~(DV_II_51_0_bit|DV_II_54_0_bit)); + if (mask & (DV_II_50_0_bit|DV_II_53_0_bit)) + mask &= (((((W[57]^W[58])>>29)&1)-1) | ~(DV_II_50_0_bit|DV_II_53_0_bit)); + if (mask & (DV_II_52_0_bit|DV_II_54_0_bit)) + mask &= ((((W[56]^(W[59]>>25))&(1<<4))-(1<<4)) | ~(DV_II_52_0_bit|DV_II_54_0_bit)); + if (mask & (DV_II_51_0_bit|DV_II_52_0_bit)) + mask &= ((0-(((W[56]^W[59])>>29)&1)) | ~(DV_II_51_0_bit|DV_II_52_0_bit)); + if (mask & (DV_II_49_0_bit|DV_II_52_0_bit)) + mask &= (((((W[56]^W[57])>>29)&1)-1) | ~(DV_II_49_0_bit|DV_II_52_0_bit)); + if (mask & (DV_II_51_0_bit|DV_II_53_0_bit)) + mask &= ((((W[55]^(W[58]>>25))&(1<<4))-(1<<4)) | ~(DV_II_51_0_bit|DV_II_53_0_bit)); + if (mask & (DV_II_50_0_bit|DV_II_52_0_bit)) + mask &= ((((W[54]^(W[57]>>25))&(1<<4))-(1<<4)) | ~(DV_II_50_0_bit|DV_II_52_0_bit)); + if (mask & (DV_II_49_0_bit|DV_II_51_0_bit)) + mask &= ((((W[53]^(W[56]>>25))&(1<<4))-(1<<4)) | ~(DV_II_49_0_bit|DV_II_51_0_bit)); + mask &= ((((W[51]^(W[50]>>5))&(1<<1))-(1<<1)) | ~(DV_I_50_2_bit|DV_II_46_2_bit)); + mask &= ((((W[48]^W[50])&(1<<6))-(1<<6)) | ~(DV_I_50_2_bit|DV_II_46_2_bit)); + if (mask & (DV_I_51_0_bit|DV_I_52_0_bit)) + mask &= ((0-(((W[48]^W[55])>>29)&1)) | ~(DV_I_51_0_bit|DV_I_52_0_bit)); + mask &= ((((W[47]^W[49])&(1<<6))-(1<<6)) | ~(DV_I_49_2_bit|DV_I_51_2_bit)); + mask &= ((((W[48]^(W[47]>>5))&(1<<1))-(1<<1)) | ~(DV_I_47_2_bit|DV_II_51_2_bit)); + mask &= ((((W[46]^W[48])&(1<<6))-(1<<6)) | ~(DV_I_48_2_bit|DV_I_50_2_bit)); + mask &= ((((W[47]^(W[46]>>5))&(1<<1))-(1<<1)) | ~(DV_I_46_2_bit|DV_II_50_2_bit)); + mask &= ((0-((W[44]^(W[45]>>5))&(1<<1))) | ~(DV_I_51_2_bit|DV_II_49_2_bit)); + mask &= ((((W[43]^W[45])&(1<<6))-(1<<6)) | ~(DV_I_47_2_bit|DV_I_49_2_bit)); + mask &= (((((W[42]^W[44])>>6)&1)-1) | ~(DV_I_46_2_bit|DV_I_48_2_bit)); + mask &= ((((W[43]^(W[42]>>5))&(1<<1))-(1<<1)) | ~(DV_II_46_2_bit|DV_II_51_2_bit)); + mask &= ((((W[42]^(W[41]>>5))&(1<<1))-(1<<1)) | ~(DV_I_51_2_bit|DV_II_50_2_bit)); + mask &= ((((W[41]^(W[40]>>5))&(1<<1))-(1<<1)) | ~(DV_I_50_2_bit|DV_II_49_2_bit)); + if (mask & (DV_I_52_0_bit|DV_II_51_0_bit)) + mask &= ((((W[39]^(W[43]>>25))&(1<<4))-(1<<4)) | ~(DV_I_52_0_bit|DV_II_51_0_bit)); + if (mask & (DV_I_51_0_bit|DV_II_50_0_bit)) + mask &= ((((W[38]^(W[42]>>25))&(1<<4))-(1<<4)) | ~(DV_I_51_0_bit|DV_II_50_0_bit)); + if (mask & (DV_I_48_2_bit|DV_I_51_2_bit)) + mask &= ((0-((W[37]^(W[38]>>5))&(1<<1))) | ~(DV_I_48_2_bit|DV_I_51_2_bit)); + if (mask & (DV_I_50_0_bit|DV_II_49_0_bit)) + mask &= ((((W[37]^(W[41]>>25))&(1<<4))-(1<<4)) | ~(DV_I_50_0_bit|DV_II_49_0_bit)); + if (mask & (DV_II_52_0_bit|DV_II_54_0_bit)) + mask &= ((0-((W[36]^W[38])&(1<<4))) | ~(DV_II_52_0_bit|DV_II_54_0_bit)); + mask &= ((0-((W[35]^(W[36]>>5))&(1<<1))) | ~(DV_I_46_2_bit|DV_I_49_2_bit)); + if (mask & (DV_I_51_0_bit|DV_II_47_0_bit)) + mask &= ((((W[35]^(W[39]>>25))&(1<<3))-(1<<3)) | ~(DV_I_51_0_bit|DV_II_47_0_bit)); +if (mask) { + + if (mask & DV_I_43_0_bit) + if ( + !((W[61]^(W[62]>>5)) & (1<<1)) + || !(!((W[59]^(W[63]>>25)) & (1<<5))) + || !((W[58]^(W[63]>>30)) & (1<<0)) + ) mask &= ~DV_I_43_0_bit; + if (mask & DV_I_44_0_bit) + if ( + !((W[62]^(W[63]>>5)) & (1<<1)) + || !(!((W[60]^(W[64]>>25)) & (1<<5))) + || !((W[59]^(W[64]>>30)) & (1<<0)) + ) mask &= ~DV_I_44_0_bit; + if (mask & DV_I_46_2_bit) + mask &= ((~((W[40]^W[42])>>2)) | ~DV_I_46_2_bit); + if (mask & DV_I_47_2_bit) + if ( + !((W[62]^(W[63]>>5)) & (1<<2)) + || !(!((W[41]^W[43]) & (1<<6))) + ) mask &= ~DV_I_47_2_bit; + if (mask & DV_I_48_2_bit) + if ( + !((W[63]^(W[64]>>5)) & (1<<2)) + || !(!((W[48]^(W[49]<<5)) & (1<<6))) + ) mask &= ~DV_I_48_2_bit; + if (mask & DV_I_49_2_bit) + if ( + !(!((W[49]^(W[50]<<5)) & (1<<6))) + || !((W[42]^W[50]) & (1<<1)) + || !(!((W[39]^(W[40]<<5)) & (1<<6))) + || !((W[38]^W[40]) & (1<<1)) + ) mask &= ~DV_I_49_2_bit; + if (mask & DV_I_50_0_bit) + mask &= ((((W[36]^W[37])<<7)) | ~DV_I_50_0_bit); + if (mask & DV_I_50_2_bit) + mask &= ((((W[43]^W[51])<<11)) | ~DV_I_50_2_bit); + if (mask & DV_I_51_0_bit) + mask &= ((((W[37]^W[38])<<9)) | ~DV_I_51_0_bit); + if (mask & DV_I_51_2_bit) + if ( + !(!((W[51]^(W[52]<<5)) & (1<<6))) + || !(!((W[49]^W[51]) & (1<<6))) + || !(!((W[37]^(W[37]>>5)) & (1<<1))) + || !(!((W[35]^(W[39]>>25)) & (1<<5))) + ) mask &= ~DV_I_51_2_bit; + if (mask & DV_I_52_0_bit) + mask &= ((((W[38]^W[39])<<11)) | ~DV_I_52_0_bit); + if (mask & DV_II_46_2_bit) + mask &= ((((W[47]^W[51])<<17)) | ~DV_II_46_2_bit); + if (mask & DV_II_48_0_bit) + if ( + !(!((W[36]^(W[40]>>25)) & (1<<3))) + || !((W[35]^(W[40]<<2)) & (1<<30)) + ) mask &= ~DV_II_48_0_bit; + if (mask & DV_II_49_0_bit) + if ( + !(!((W[37]^(W[41]>>25)) & (1<<3))) + || !((W[36]^(W[41]<<2)) & (1<<30)) + ) mask &= ~DV_II_49_0_bit; + if (mask & DV_II_49_2_bit) + if ( + !(!((W[53]^(W[54]<<5)) & (1<<6))) + || !(!((W[51]^W[53]) & (1<<6))) + || !((W[50]^W[54]) & (1<<1)) + || !(!((W[45]^(W[46]<<5)) & (1<<6))) + || !(!((W[37]^(W[41]>>25)) & (1<<5))) + || !((W[36]^(W[41]>>30)) & (1<<0)) + ) mask &= ~DV_II_49_2_bit; + if (mask & DV_II_50_0_bit) + if ( + !((W[55]^W[58]) & (1<<29)) + || !(!((W[38]^(W[42]>>25)) & (1<<3))) + || !((W[37]^(W[42]<<2)) & (1<<30)) + ) mask &= ~DV_II_50_0_bit; + if (mask & DV_II_50_2_bit) + if ( + !(!((W[54]^(W[55]<<5)) & (1<<6))) + || !(!((W[52]^W[54]) & (1<<6))) + || !((W[51]^W[55]) & (1<<1)) + || !((W[45]^W[47]) & (1<<1)) + || !(!((W[38]^(W[42]>>25)) & (1<<5))) + || !((W[37]^(W[42]>>30)) & (1<<0)) + ) mask &= ~DV_II_50_2_bit; + if (mask & DV_II_51_0_bit) + if ( + !(!((W[39]^(W[43]>>25)) & (1<<3))) + || !((W[38]^(W[43]<<2)) & (1<<30)) + ) mask &= ~DV_II_51_0_bit; + if (mask & DV_II_51_2_bit) + if ( + !(!((W[55]^(W[56]<<5)) & (1<<6))) + || !(!((W[53]^W[55]) & (1<<6))) + || !((W[52]^W[56]) & (1<<1)) + || !((W[46]^W[48]) & (1<<1)) + || !(!((W[39]^(W[43]>>25)) & (1<<5))) + || !((W[38]^(W[43]>>30)) & (1<<0)) + ) mask &= ~DV_II_51_2_bit; + if (mask & DV_II_52_0_bit) + if ( + !(!((W[59]^W[60]) & (1<<29))) + || !(!((W[40]^(W[44]>>25)) & (1<<3))) + || !(!((W[40]^(W[44]>>25)) & (1<<4))) + || !((W[39]^(W[44]<<2)) & (1<<30)) + ) mask &= ~DV_II_52_0_bit; + if (mask & DV_II_53_0_bit) + if ( + !((W[58]^W[61]) & (1<<29)) + || !(!((W[57]^(W[61]>>25)) & (1<<4))) + || !(!((W[41]^(W[45]>>25)) & (1<<3))) + || !(!((W[41]^(W[45]>>25)) & (1<<4))) + ) mask &= ~DV_II_53_0_bit; + if (mask & DV_II_54_0_bit) + if ( + !(!((W[58]^(W[62]>>25)) & (1<<4))) + || !(!((W[42]^(W[46]>>25)) & (1<<3))) + || !(!((W[42]^(W[46]>>25)) & (1<<4))) + ) mask &= ~DV_II_54_0_bit; + if (mask & DV_II_55_0_bit) + if ( + !(!((W[59]^(W[63]>>25)) & (1<<4))) + || !(!((W[57]^(W[59]>>25)) & (1<<4))) + || !(!((W[43]^(W[47]>>25)) & (1<<3))) + || !(!((W[43]^(W[47]>>25)) & (1<<4))) + ) mask &= ~DV_II_55_0_bit; + if (mask & DV_II_56_0_bit) + if ( + !(!((W[60]^(W[64]>>25)) & (1<<4))) + || !(!((W[44]^(W[48]>>25)) & (1<<3))) + || !(!((W[44]^(W[48]>>25)) & (1<<4))) + ) mask &= ~DV_II_56_0_bit; +} + + dvmask[0]=mask; +} diff --git a/src/hash/sha1dc/ubc_check.h b/src/hash/sha1dc/ubc_check.h new file mode 100644 index 000000000..27285bdf5 --- /dev/null +++ b/src/hash/sha1dc/ubc_check.h @@ -0,0 +1,35 @@ +/*** +* Copyright 2017 Marc Stevens , Dan Shumow +* Distributed under the MIT Software License. +* See accompanying file LICENSE.txt or copy at +* https://opensource.org/licenses/MIT +***/ + +// this file was generated by the 'parse_bitrel' program in the tools section +// using the data files from directory 'tools/data/3565' +// +// sha1_dvs contains a list of SHA-1 Disturbance Vectors (DV) to check +// dvType, dvK and dvB define the DV: I(K,B) or II(K,B) (see the paper) +// dm[80] is the expanded message block XOR-difference defined by the DV +// testt is the step to do the recompression from for collision detection +// maski and maskb define the bit to check for each DV in the dvmask returned by ubc_check +// +// ubc_check takes as input an expanded message block and verifies the unavoidable bitconditions for all listed DVs +// it returns a dvmask where each bit belonging to a DV is set if all unavoidable bitconditions for that DV have been met +// thus one needs to do the recompression check for each DV that has its bit set + +#ifndef UBC_CHECK_H +#define UBC_CHECK_H + +#include + +#define DVMASKSIZE 1 +typedef struct { int dvType; int dvK; int dvB; int testt; int maski; int maskb; uint32_t dm[80]; } dv_info_t; +extern dv_info_t sha1_dvs[]; +void ubc_check(const uint32_t W[80], uint32_t dvmask[DVMASKSIZE]); + +#define DOSTORESTATE58 +#define DOSTORESTATE65 + + +#endif // UBC_CHECK_H From d087c8f80ecbbbfca2740392cbf84816019f4d49 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Fri, 24 Feb 2017 14:14:56 +0000 Subject: [PATCH 169/366] hash: test for sha1 collision attack detection --- tests/core/sha1.c | 64 +++++++++++++++++++++++++++ tests/resources/sha1/hello_c | Bin 0 -> 89 bytes tests/resources/sha1/shattered-1.pdf | Bin 0 -> 422435 bytes 3 files changed, 64 insertions(+) create mode 100644 tests/core/sha1.c create mode 100644 tests/resources/sha1/hello_c create mode 100644 tests/resources/sha1/shattered-1.pdf diff --git a/tests/core/sha1.c b/tests/core/sha1.c new file mode 100644 index 000000000..c5b20f6e0 --- /dev/null +++ b/tests/core/sha1.c @@ -0,0 +1,64 @@ +#include "clar_libgit2.h" +#include "hash.h" + +#define FIXTURE_DIR "sha1" + +void test_core_sha1__initialize(void) +{ + cl_fixture_sandbox(FIXTURE_DIR); +} + +void test_core_sha1__cleanup(void) +{ + cl_fixture_cleanup(FIXTURE_DIR); +} + +static int sha1_file(git_oid *oid, const char *filename) +{ + git_hash_ctx ctx; + char buf[2048]; + int fd, ret; + ssize_t read_len; + + fd = p_open(filename, O_RDONLY); + cl_assert(fd >= 0); + + cl_git_pass(git_hash_ctx_init(&ctx)); + + while ((read_len = p_read(fd, buf, 2048)) > 0) + cl_git_pass(git_hash_update(&ctx, buf, (size_t)read_len)); + + cl_assert_equal_i(0, read_len); + p_close(fd); + + ret = git_hash_final(oid, &ctx); + git_hash_ctx_cleanup(&ctx); + + return ret; +} + +void test_core_sha1__sum(void) +{ + git_oid oid, expected; + + cl_git_pass(sha1_file(&oid, FIXTURE_DIR "/hello_c")); + git_oid_fromstr(&expected, "4e72679e3ea4d04e0c642f029e61eb8056c7ed94"); + cl_assert_equal_oid(&expected, &oid); +} + +/* test that sha1 collision detection works when enabled */ +void test_core_sha1__detect_collision_attack(void) +{ + git_oid oid, expected; + +#ifdef GIT_SHA1_COLLISIONDETECT + GIT_UNUSED(expected); + cl_git_fail(sha1_file(&oid, FIXTURE_DIR "/shattered-1.pdf")); + cl_assert_equal_s("SHA1 collision attack detected", giterr_last()->message); +#else + cl_git_pass(sha1_file(&oid, FIXTURE_DIR "/shattered-1.pdf")); + git_oid_fromstr(&expected, "38762cf7f55934b34d179ae6a4c80cadccbb7f0a"); + cl_assert_equal_oid(&expected, &oid); +#endif +} + diff --git a/tests/resources/sha1/hello_c b/tests/resources/sha1/hello_c new file mode 100644 index 0000000000000000000000000000000000000000..45950b2ad2add6f8b5c8a0dd28dfd19bf7a8d3a3 GIT binary patch literal 89 zcmY$+%uCKGO-WU-DK1IL%-74X`Sl8%B>d45q&ijt-^S1lI+8`c}l literal 0 HcmV?d00001 diff --git a/tests/resources/sha1/shattered-1.pdf b/tests/resources/sha1/shattered-1.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ba9aaa145ccd24ef760cf31c74d8f7ca1a2e47b0 GIT binary patch literal 422435 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 z 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 z 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

# zj%qo!c`SDdX}e~F0oy4=hTE}j!bLB6_-;OmU%OJJev7!J@;q=->MM0^$c%o?YsmG{ zgh&7h}#;U7=7X1z2r^*E*M-iJy2VY7f;yR3jSP_K9xfndK$VmYMa1 zJ?y}g$6r4epi3yO+?g-ovIfUyeo?WuO4RJL)SdJEClY=Van5CPcwp2J;)d_d-}Y{9 z55Fbv<=s+Eq3c5P36o!;Q7f@V_M2#3D`?og!sD_;% zJPHZhRz`%eAR%&BhHSBtBCB)$FT52}-@@(^R}7u<7&2^_*K_@5`Q7r2XoOg*xjKGWKXOf zfVuiCt7wn8>?i4o*}$KGw(a|(^PGr+Qvq+BY`Nrw%agoJe^paCP-;~wZmbM%lt&uD zy525u8^}b{sn-+-Ckz{i`@=BZQIw0cDeCz;Lg{)|jIC=rA(d3?jdv*9oS{%r=vz*r zO>&t*%C{-Rf(zbW*THryl|yY752FY$wP+eZwr$ZEi3 zXi&7seBFYPCq8VtBkN1Ur_)!W%Xb>%i;nN~;~KK;*#Tj3L1pOILu?1ii>?c36Vj1i zV0T3^gciM*JQFbH{JGBvE#UqW?q=jmCq3gn75f8u8H1nBJ z@k8ED{34L(6B+gyRyo6c2q^>g(MaW}GjDaCM`eQe2t0a0;aQiu{Z5U!WBw=+H{hD;-@xuWnw738<~-N7tmdUPu_GEQ9u0|Xk^kAzw=MgjXSm*j!Xo0B_SGr z=YvaaNr3&R`_yx4rj^2YvqnTIi$qs{OvQNO}g6s6Au za?RDLP`gmJzHv%;Kdz~ zUbgv)22+)jthBc)ym~~o)>@?y6C{Hg@~ON%f_hJ}Yv2`CH|Vv;S-VJ#%8xJtRlqy{ z)Y%VtE6tE5B9-R|7i{}t7bxJ?g&mC(-Od+l@a1T_7`aJ+?L9E_psCN|60mCH=9mgY6#0QR ztF&_oYC?|3T%hDGOFc`Z=$-&&I>`;fSydy?l>uql*68$A7mC*>RmavCHRaiSw)oDrm`-ma_&v-3spZ>-mUPA}6|V*TMg0KEQTK-+fs*Js<# zZo*Bk+(z{Hc2))p~i9L~C zAm5Ufe~vMr1GPF7tnFbbr@Y2u#kU%@yj@e88v-Ip+umY){YD~H#@DsU_1B3IkKAl+ zfy1flZw5V<$oVC|GjDx=c+;e>h#AwD(5~w8RjR`}1S<^>1YC!+{4dtFLb7C}IuY%k zo&B3&_*+{~B06Q_Rh2=U+BzuY<7(5DkB z(A&GfcE3`Nb2kg(FY@6VU;pQ@B+%IELj1&Z^t*q$Do+%pC>`CU0U$!-ub=CG2W|BSdG>jch^FJ=4 zK4{}5sf_EmwQEcJ#Z<#YU`p8YZk@j6Fuo)#w=Sa??bMW3AbmM6Q^ZJDdA{5z{G^Fo z*|xzJ@&|T?R3!C0B{Ul;uD6=z7D;}B%!IhFjT^%gh^E2|XHvh_zXHhIi9yKw7MY1x zut74D>FN*46}oyVCcdj=1Ys!J-;9sVQJ%k|kh~0kuC?xH0WR-{^-cOso>7hd@j)f! zE_0lzxA@+v1pp}jeJk=M-M%bvI$s&VNga>TJyvE|`my9P`^@N>!|9BUO9_)Y^(lPG zxZHb3=|yURf-hU^DKp1?CE3cEL4F5e-?OYE1MSGyv64tR&cZ-zBkn{4J!9V1&g7NV zXNA*uW%_Iw^kLEFdb=P=L-bgueg$mQZ@IDj?0h*2vK%wxvg#68;)e|h<}4{B6>U`r zvr3bhDvCq%gug3n$P%(@z8}r<5S6;k#ROPkhq|vMfhV_c>eZRg*~Vwa&qGY&tc*YsNjP^NC+sb~n^XYC z?R*2X+X;w#fDUtxZQ`oNRn3rl^qr`NvU!tsP;9X<%VEmGlJa(&Q{+nZ3*UL%68= zZ()=s309>PF-9bv9P4~(w6!iQ>Kn$nq{G1RdhiN(S?L7zYIHGL31h{L=P3(uHbm)$Iam2VX zO#e-9L`RN&FwDKRYgS$LL1eTIzl`PT?WRfsZ8(i1|BjgT*V?c~hN@fwHVa-aEsd&8l z?CzGIh=F+qHQ8Z2EPpyNuF6ULmT)ahz;!573+XmY-SiIh`s#!CWl-$NU?C0wInmD= z2n3}UuJXm`T)zLz^}{#;O(K_M)qh`NIh(b0r!Q}Pi+0p}_ZV*z4snw7%vI=${%};_ z-`&!Ze8`zOgbG3|-?6VzOUlfPhg{yx;d#{^if-dC%#AVUyp;3t*9jY0st_e2f@y%0 z7|Ob^a@&_|KQz@*`;p&>wdmO|ss?@u70?S*fUS+RKaKc-v3pSZ@dTTt0Jtw~yR^pB}M&XoYVRp_r4 z4fPp8+Of@mN@g&^@%2Ob*~=$>rN0Y68ff7UvYr6#ktv{PdeyI@4&+2PvjvE^M+5E9 zz0$_W?F>jE-|#ZgbNIxq;BjU|?w2a4Z)(}+m#rIibyj-^EYR23_;JiE+d1`PxPv}6 z%|#k6LhXOadRXBlQKyqL4{at;3x9PEEfunHCeGj_Y}Qvs)cg7kPU|tgO(L9;)r)En zjrzdCimQx)w21iyHW&TQHL>_%vfI@%(&bUEfS2v_x`+4qv0i6C?P!@t<5tWf^%_pw zy0+uQSVe{C(&vb==HkGf5Z@wi(euXdm_nJ`zN`t`2)glgL|DNBbZ&bhi)$o;Fjaol zvC0mdj2>U({5P%V{fO4$h+)57sh6iOsfQz4hNte|8d#1tR2u9dW*hTXmzm9R|Ji;A}<*DYaQ#OLNi5}J)hB~muS-091;eB*d4j&vm~bp z10Riirh)61yy1z~>M|NuVtQ=T43Tth)8P6mWqRB&a6e83Cw~qy&(p-nIZ^{8Og!{L z`{y}GBrVz<{jDRT{)5MsARq>QNQvZYFFf`wr+itdQb;Dqs~^Xf*JR;82L9o8z-pou zsytP`X9xn_8%;%zrni9ja=*+48o5|w`f%3`GTk%r)-UmC1lufS0kW5mp5#Fw?d$cF zfx)$u_(iDTCR0NQ<$Tdp6zD6*hqX|cqQRDBK|Xbyt;Q=Zw|-Z!ZCA3c5KMAAU^6^i&;wBOYT=HRauHrjHG`unxKb8TRSs#??=Tpe=D+DsyP4D5yEtfzCvU9%X^r-gM9F|*n!ztoY+NhRYHFpP)wn|Jw zfD18xt4mI!wDY?USKF+HRI(nM8Ck4m|7a4lS=+U;Nw}Tkz({^xcZa;}S6%n@cs#Q= z_S1N#y_NCigOK_w&N(}KmyI|tXkuw|ts2}5seKCYv)L}au2)nvl7r0!Adu#zMioA5 zn1DH78qqoHiR1Q&c6<}q-;)nkZfT8qhDNM?1E<9V#R)OTZw+gpmDyJDR!~6-6Z=NJJD~RleLqcP2&t6%H)KTp;p{BA0cB!N0{xF9)t%>Ya(x zMz>Kh32IIEIxAh~#H^Wx)zk)w4wcfNVAJ8Eq*R@ zwrol{(vU)(^-%w=7oD|6ikWk*F8Gyfan(uEPMw$Z9F1d#h`E_%- z8!Z0IYw15?>}X(qmRq*IPD3KSY&-FxvfhSejj?#M>$-~a+dhOFFdV=H8$|?6ih1gW zvF<~IT!~rY9iaD>z#3QC+_f{(>kK?i0ehL10(~}2%*j(J}RY<5!FwJ zm=@Lp?&B4*4>M;K;8H2rJ%baY7Lr{#uij$^-hHD2C0jeriwTJIF@$xiISQ0f7D